initial commit

This commit is contained in:
mikhail "synzr" 2025-12-25 01:37:49 +05:00
commit 9d20827c46
2469 changed files with 470994 additions and 0 deletions

76
third-party/JsonQt/lib/CMakeLists.txt vendored Normal file
View file

@ -0,0 +1,76 @@
SET(
CLASSES
ParseException
JsonRpc
JsonRpcAdaptor
JsonRpcAdaptorPrivate
JsonToProperties
JsonToVariant
VariantToJson
)
SET(HEADERS JsonQtExport.h)
SET(VERSION 0.1.0)
##### Probably don't want to edit below this line #####
# Find Qt4
FIND_PACKAGE( Qt4 REQUIRED )
SET( QT_DONT_USE_QTGUI TRUE )
# Include the cmake file needed to use qt4
INCLUDE( ${QT_USE_FILE} )
# Include the binary directory for moc files.
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
FOREACH(class ${CLASSES})
QT4_WRAP_CPP(MOC_SOURCE ${class}.h)
SET(SOURCES ${SOURCES} ${class}.cpp ${MOC_SOURCE})
SET(HEADERS ${HEADERS} ${class}.h)
ENDFOREACH()
SET(SOURCES ${SOURCES} ${MOC_SOURCE})
IF("${STATIC_JSONQT}" STREQUAL "")
OPTION(STATIC_JSONQT "Build static libraries of JsonQt instead of shared" OFF)
ENDIF()
IF(STATIC_JSONQT)
SET(BUILD STATIC)
ELSE()
SET(BUILD SHARED)
ENDIF()
MESSAGE(STATUS "Building ${BUILD} JsonQt")
ADD_LIBRARY(
JsonQt
${BUILD}
${SOURCES}
)
SET_TARGET_PROPERTIES(
JsonQt
PROPERTIES
VERSION "${VERSION}"
SOVERSION "0"
)
TARGET_LINK_LIBRARIES(
JsonQt
${QT_LIBRARIES}
)
INSTALL(
TARGETS
JsonQt
DESTINATION
lib${LIB_SUFFIX}
)
INSTALL(
FILES
${HEADERS}
DESTINATION
include/JsonQt
)

24
third-party/JsonQt/lib/JsonQtExport.h vendored Normal file
View file

@ -0,0 +1,24 @@
/* LICENSE NOTICE
Copyright (c) 2008, Frederick Emmott <mail@fredemmott.co.uk>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _JSONQT_EXPORT_H
#define _JSONQT_EXPORT_H
#include <QtGlobal>
#define JSONQT_EXPORT Q_DECL_EXPORT
#endif

167
third-party/JsonQt/lib/JsonRpc.cpp vendored Normal file
View file

@ -0,0 +1,167 @@
#include "JsonRpc.h"
#include "JsonToVariant.h"
#include "VariantToJson.h"
#include <QDebug>
namespace JsonQt
{
JsonRpc::JsonRpc(QObject* parent) : QObject(parent) {}
void JsonRpc::sendRequest(const QVariant& id, const QString& method, const QVariant& parameters)
{
Q_ASSERT(parameters.type() == QVariant::List || parameters.type() == QVariant::Map || parameters.isNull());
QVariantMap request;
request["jsonrpc"] = "2.0";
request["method"] = method;
request["id"] = id;
if(!parameters.isNull())
{
request["params"] = parameters;
}
emit sendJson(VariantToJson::parse(request));
}
void JsonRpc::sendNotification(const QString& method, const QVariant& parameters)
{
Q_ASSERT(parameters.type() == QVariant::List || parameters.type() == QVariant::Map || parameters.isNull());
QVariantMap request;
request["jsonrpc"] = "2.0";
request["method"] = method;
// no ID for notifications.
if(!parameters.isNull())
{
request["params"] = parameters;
}
emit sendJson(VariantToJson::parse(request));
}
void JsonRpc::sendResponse(const QVariant& id, const QVariant& result)
{
QVariantMap response;
response["jsonrpc"] = "2.0";
response["id"] = id;
response["result"] = result;
emit sendJson(VariantToJson::parse(response));
}
void JsonRpc::sendError(const QVariant& id, int errorCode, const QString& message, const QVariant& data)
{
QVariantMap error;
error["code"] = errorCode;
error["message"] = message;
error["data"] = data;
QVariantMap response;
response["jsonrpc"] = "2.0";
response["id"] = id;
response["error"] = error;
emit sendJson(VariantToJson::parse(response));
}
void JsonRpc::processJson(const QString& json)
{
QList<QVariantMap> objects;
try
{
objects = JsonToVariant::multiParse(json);
}
catch(ParseException)
{
sendError(QVariant(), InvalidJson, "Parse error.");
return;
}
Q_FOREACH(const QVariantMap& object, objects)
{
if(object.value("jsonrpc").toString() != "2.0")
{
sendError(object.value("id"), InvalidJsonRpc, "JSON-RPC version not specified or not supported.", object);
continue;
}
// Notification or request
if(object.contains("method"))
{
if(object.value("method").type() != QVariant::String)
{
sendError(object.value("id"), InvalidJsonRpc, "'method' member of request must be a string.", object);
continue;
}
QString method = object.value("method").toString();
QVariant parameters = object.value("params");
if(parameters.isNull()) parameters = QVariantList();
if(parameters.type() != QVariant::List && parameters.type() != QVariant::Map)
{
sendError(object.value("id"), InvalidJsonRpc, "'parameters' member of request must be omitted, a list, or an object.", object);
continue;
}
// Request or notification
if(object.contains("id"))
{
emit requestReceived(object.value("id"), method, parameters);
}
else
{
emit notificationReceived(method, parameters);
}
continue;
}
// Request successful
if(object.contains("result"))
{
if(!object.contains("id"))
{
sendError(QVariant(), InvalidJsonRpc, "ID not specified in response.", object);
continue;
}
emit responseReceived(object.value("id"), object.value("result"));
continue;
}
// Request failed
if(object.contains("error"))
{
if(!object.contains("id"))
{
sendError(QVariant(), InvalidJsonRpc, "ID not specified in response.", object);
continue;
}
if(object.value("error").type() != QVariant::Map)
{
sendError(object.value("id"), InvalidJsonRpc, "'error' member is not an Error object.", object);
continue;
}
QVariantMap error = object.value("error").toMap();
if(error.value("code").type() != QVariant::Int)
{
sendError(object.value("id"), InvalidJsonRpc, "'code' member of error object is not an integer.", object);
continue;
}
if(error.value("message").type() != QVariant::String)
{
sendError(object.value("id"), InvalidJsonRpc, "'message' member of error object is not a string.", object);
continue;
}
emit errorReceived(object.value("id"), error.value("code").toInt(), error.value("message").toString(), error.value("data"));
continue;
}
// Not a notification, request, or response
sendError(object.value("id"), InvalidJsonRpc, "JSON object doesn't appear to be a JSON-RPC request, notification, or response.", object);
}
}
};

105
third-party/JsonQt/lib/JsonRpc.h vendored Normal file
View file

@ -0,0 +1,105 @@
#ifndef _JSONQT_JSON_RPC_H
#define _JSONQT_JSON_RPC_H
#include "JsonQtExport.h"
#include <QObject>
#include <QVariant>
namespace JsonQt
{
/** Class implementing JSON-RPC.
*
* This implements the JSON-RPC 2.0 proposal, as of 2008-11-15, located
* at http://groups.google.com/group/json-rpc/web/json-rpc-1-2-proposal.
*
* While 1.1 is more popular for web services, 2.0 is a much simpler
* protocol, and is not restricted to HTTP requests.
*
* Note that 'parameter' QVariant objects must be either null QVariants,
* contain a QVariantList, or a QVariantMap. If a QVariantList is used,
* it must be a list of all the parameters the method takes, in the
* correct order. If a QVariantMap is used, the keys must be strings
* exactly matching the parameter names of the method (case-sensitive).
*
* There are two IO members:
* - processJson - slot - parse the JSON string given, and act upon it
* - sendJson - signal - an action that an instance of JsonRpc has been
* told to do requires that the specified JSON be sent to the other
* peer.
*
* All other members are interfaces to JSON-RPC.
*
* 'id' parameters SHOULD NOT be NULL, for reasons defined in the
* specification. Also, it SHOULD be a scalar.
*
* @author Fred Emmott <mail@fredemmott.co.uk>
*/
class JSONQT_EXPORT JsonRpc : public QObject
{
Q_OBJECT
public:
Q_ENUMS(ErrorCode);
/** List of standard JSON-RPC error codes.
* All error codes between ServerErrorLow and
* ServerErrorHigh are reserved for
* implementation-defined server errors.
*
* All codes between -32768 and -32000 are reserved
* either for the definitions below, or for future use.
*
* Other values may be used.
*
* InvalidJson and InvalidJsonRpc should only
* be used internally by this class.
*
*/
enum ErrorCode
{
InvalidJson = -32700,
InvalidJsonRpc = -32600,
MethodNotFound = -32601,
BadParameters = -32602,
InternalError = -32603,
ServerErrorLow = -32099,
ServerErrorHigh = -32000
};
/// Construct a JsonRpc object.
JsonRpc(QObject* parent = NULL);
/// Send a request, expecting a response.
void sendRequest(const QVariant& id, const QString& method, const QVariant& parameters = QVariant());
/// Send a request, not expecting a response.
void sendNotification(const QString& method, const QVariant& parameters = QVariant());
/// Respond to a request with success.
void sendResponse(const QVariant& id, const QVariant& result = QVariant());
/// Respond to a request with an error.
void sendError(const QVariant& id, int errorCode, const QString& message, const QVariant& data = QVariant());
public slots:
/** Process a received JSON string, and emit the
* appropriate signals.
*/
void processJson(const QString& json);
signals:
/** Emitted when JsonRpc needs to send some JSON to the
* other peer.
*/
void sendJson(const QString& json);
/** A notification has been received from the other peer.
* No reponse is neccessary.
*/
void notificationReceived(const QString& method, const QVariant& parameters);
/** A request has been received from the other peer.
* A response (with the same id) is required.
*/
void requestReceived(const QVariant& id, const QString& method, const QVariant& parameters);
/// A successful response has been received from the other peer.
void responseReceived(const QVariant& id, const QVariant& result);
/// An error has been recevied from the other peer.
void errorReceived(const QVariant& id, int errorCode, const QString& message, const QVariant& data);
};
};
#endif

View file

@ -0,0 +1,19 @@
#include "JsonRpcAdaptor.h"
#include "JsonRpcAdaptorPrivate.h"
namespace JsonQt
{
JsonRpcAdaptor::JsonRpcAdaptor(QObject* adapt, QObject* parent)
:
QObject(parent),
d(new JsonRpcAdaptorPrivate(adapt, this))
{
connect(d, SIGNAL(sendJson(const QString&)), this, SIGNAL(sendJson(const QString&)));
}
void JsonRpcAdaptor::processJson(const QString& json)
{
d->processJson(json);
}
};

69
third-party/JsonQt/lib/JsonRpcAdaptor.h vendored Normal file
View file

@ -0,0 +1,69 @@
#ifndef _JSONQT_JSON_RPC_ADAPTOR_H
#define _JSONQT_JSON_RPC_ADAPTOR_H
#include "JsonQtExport.h"
#include <QObject>
namespace JsonQt
{
class JsonRpcAdaptorPrivate;
/** Class exporting a QObject's public slots via JSON-RPC.
*
* This implements the JSON-RPC 2.0 proposal, as of 2008-11-15, located
* at http://groups.google.com/group/json-rpc/web/json-rpc-1-2-proposal.
*
* It also implements the introspection functionality of JSON-RPC 1.1.
*
* There are several Q_CLASSINFO declarations that this adaptor will pay
* attention to:
*
* - JsonQt-RPC-id: *REQUIRED*. This is the only required parameter; it
* specifies a unique identifier for this service, in the format
* described by RFC 3986.
*
* - JsonQt-RPC-name: the name of the service provided by the QObject.
* If this is not specified, the class name will be used.
*
* - JsonQt-RPC-version: the version of the service provided by the QObject.
* If this is omitted, it will be omitted from the introspection data.
*
* - JsonQt-RPC-summary: A short description of this service. If this
* is omitted, it will be omitted from the introspection data.
*
* - JsonQt-RPC-help: An URL pointing to human-readable documentation
* about the service. If this is omitted, it will be omitted from the
* introspection data.
*
* The following types are supported for parameters and return values:
* - void return
* - bool
* - int
* - QString
* - QVariantList (which can contain any types supported by JsonQt)
* - QVariantMap (which can contain any types supported by JsonQt)
*
* @author Fred Emmott <mail@fredemmott.co.uk>
*/
class JSONQT_EXPORT JsonRpcAdaptor : public QObject
{
Q_OBJECT
public:
/** Construct a JsonRpcAdaptor.
* This will expose @param adapt via JSON.
*/
JsonRpcAdaptor(QObject* adapt, QObject* parent = NULL);
public slots:
/// Handle received JSON.
void processJson(const QString& json);
signals:
/** When this is emitted, the JSON provided should be
* sent to the peer.
*/
void sendJson(const QString& json);
private:
JsonRpcAdaptorPrivate* d;
};
};
#endif

View file

@ -0,0 +1,351 @@
#include "JsonRpcAdaptorPrivate.h"
#include "VariantToJson.h"
#include <QDebug>
#include <QGenericArgument>
#include <QMetaClassInfo>
#include <QMetaObject>
namespace JsonQt
{
JsonRpcAdaptorPrivate::JsonRpcAdaptorPrivate(QObject* adapt, QObject* parent) : QObject(parent)
{
m_adapted = adapt;
connect(
&m_jsonRpc,
SIGNAL(sendJson(const QString&)),
this,
SIGNAL(sendJson(const QString&))
);
connect(
&m_jsonRpc,
SIGNAL(requestReceived(const QVariant&, const QString&, const QVariant&)),
this,
SLOT(requestReceived(const QVariant&, const QString&, const QVariant&))
);
populateServiceDescription();
}
void JsonRpcAdaptorPrivate::populateServiceDescription()
{
m_serviceDescription.clear();
const QMetaObject* metaObject = m_adapted->metaObject();
QString id = getClassInfo("JsonQt-RPC-id");
Q_ASSERT(!id.isEmpty());
m_serviceDescription["id"] = id;
m_serviceDescription["sdversion"] = "1.0";
QString name = getClassInfo("JsonQt-RPC-name");
if(name.isEmpty()) name = metaObject->className();
m_serviceDescription["name"] = name;
QString version = getClassInfo("JsonQt-RPC-version");
if(!version.isNull()) m_serviceDescription["version"] = version;
QString summary = getClassInfo("JsonQt-RPC-summary");
if(!summary.isNull()) m_serviceDescription["summary"] = summary;
QString help = getClassInfo("JsonQt-RPC-help");
if(!help.isNull()) m_serviceDescription["help"] = help;
QMap<QString, QString> typeMap;
typeMap[""] = "nil"; // void
typeMap["bool"] = "bit";
typeMap["int"] = "num";
typeMap["QString"] = "str";
// typeMap["QVariant"] = "any"; // not supported
typeMap["QVariantList"] = "arr";
typeMap["QVariantMap"] = "obj";
QVariantList procs;
for(int i = metaObject->methodOffset(); i < metaObject->methodCount(); ++i)
{
QMetaMethod method = metaObject->method(i);
// Check we should export it
if(method.access() != QMetaMethod::Public || method.methodType() != QMetaMethod::Slot) continue;
QVariantMap proc;
QString signature = method.signature();
// Name
QString methodName = signature.left(signature.indexOf('('));
proc["name"] = methodName;
// Return type
if(!typeMap.contains(method.typeName()))
{
qDebug() << "Public slot" << signature << "has unknown return type" << method.typeName();
continue;
}
proc["return"] = typeMap.value(method.typeName());
// Parameters
QVariantList parameters;
bool badParameter = false;
for(int i = 0; i < method.parameterNames().count(); ++i)
{
QVariantMap parameter;
QString parameterName(method.parameterNames().at(i));
parameter["name"] = parameterName;
QString parameterType = method.parameterTypes().at(i);
if(!typeMap.contains(method.parameterTypes().at(i)))
{
qDebug() << "Public slot" << signature << "has parameter" << parameterName << "with unknown type" << parameterType;
badParameter = true;
continue;
}
parameter["type"] = typeMap.value(parameterType);
parameters.append(parameter);
m_parameterIndices[methodName].insert(parameterName, i);
}
if(badParameter) continue;
m_methods.insert(methodName, method);
proc["params"] = parameters;
// Done
procs.append(proc);
}
m_serviceDescription["procs"] = procs;
}
QString JsonRpcAdaptorPrivate::getClassInfo(const char* name)
{
const QMetaObject* metaObject = m_adapted->metaObject();
int index = metaObject->indexOfClassInfo(name);
if(index == -1) return QString();
return metaObject->classInfo(index).value();
}
void JsonRpcAdaptorPrivate::requestReceived(const QVariant& id, const QString& method, const QVariant& parameters)
{
if(method == "system.describe")
{
m_jsonRpc.sendResponse(id, m_serviceDescription);
return;
}
ReturnData result = invokeMethod(method, parameters);
if(result.succeeded)
{
m_jsonRpc.sendResponse(id, result.data);
}
else
{
m_jsonRpc.sendError(id, result.code, result.message, result.data);
}
}
JsonRpcAdaptorPrivate::ReturnData JsonRpcAdaptorPrivate::invokeMethod(const QString& methodName, const QVariant& parameters)
{
ReturnData ret;
ret.succeeded = false;
if(!m_methods.contains(methodName))
{
ret.code = JsonRpc::MethodNotFound;
ret.message = QString("The method %1 does not exist.").arg(methodName);
return ret;
}
QMetaMethod metaMethod(m_methods.value(methodName));
int parameterCount;
QVariantList parameterList;
switch(parameters.type())
{
case QVariant::List:
parameterList = parameters.toList();
parameterCount = parameterList.count();
break;
case QVariant::Map:
parameterCount = parameters.toMap().count();
for(int i = 0; i < parameterCount; ++i)
{
parameterList.append(QVariant());
}
break;
default:
parameterCount = 0;
}
Q_ASSERT(parameterCount <= 9);
ret.code = JsonRpc::BadParameters;
if(parameterCount != metaMethod.parameterNames().count())
{
ret.message = "Parameter count mismatch.";
return ret;
}
if(parameters.type() == QVariant::Map)
{
QMap<QString, int> parameterIndices = m_parameterIndices.value(methodName);
QVariantMap parameterMap = parameters.toMap();
for(QVariantMap::ConstIterator it = parameterMap.constBegin(); it != parameterMap.constEnd(); ++it)
{
if(!parameterIndices.contains(it.key()))
{
ret.message = QString("'%1' is not a parameter of method '%2'.").arg(it.key()).arg(methodName);
return ret;
}
int index = parameterIndices.value(it.key());
Q_ASSERT(index < parameterCount);
parameterList[index] = it.value();
}
}
QMap<QString, QVariant::Type> typeMap;
typeMap[""] = QVariant::Invalid;
typeMap["bool"] = QVariant::Bool;
typeMap["int"] = QVariant::Int;
typeMap["QString"] = QVariant::String;
typeMap["QVariantList"] = QVariant::List;
typeMap["QVariantMap"] = QVariant::Map;
///@todo more types
QVariant::Type returnType = typeMap.value(metaMethod.typeName());
// QMetaObject::invokeMethod takes 9 generic arguments
QGenericArgument arguments[9];
for(int i = 0; i < parameterCount; ++i)
{
const QVariant& value = parameterList.value(i);
if(typeMap.value(metaMethod.parameterTypes().at(i)) != value.type())
{
ret.message = QString("Value for parameter %1 was not of the correct type.").arg(QString(metaMethod.parameterNames().at(i)));
return ret;
}
void* data = 0;
switch(value.type())
{
case QVariant::Bool:
data = new bool(value.toBool());
arguments[i] = Q_ARG(bool, *static_cast<bool*>(data));
break;
case QVariant::Int:
data = new int(value.toInt());
arguments[i] = Q_ARG(int, *static_cast<int*>(data));
break;
case QVariant::String:
data = new QString(value.toString());
arguments[i] = Q_ARG(QString, *static_cast<QString*>(data));
break;
case QVariant::List:
data = new QVariantList(value.toList());
arguments[i] = Q_ARG(QVariantList, *static_cast<QVariantList*>(data));
break;
case QVariant::Map:
data = new QVariantMap(value.toMap());
arguments[i] = Q_ARG(QVariantMap, *static_cast<QVariantMap*>(data));
break;
default:
break;
}
}
QGenericReturnArgument returnValue;
switch(returnType)
{
case QVariant::Bool:
returnValue = Q_RETURN_ARG(bool, *(new bool));
break;
case QVariant::Int:
returnValue = Q_RETURN_ARG(int, *(new int));
break;
case QVariant::String:
returnValue = Q_RETURN_ARG(QString, *(new QString));
break;
case QVariant::List:
returnValue = Q_RETURN_ARG(QVariantList, *(new QVariantList));
break;
case QVariant::Map:
returnValue = Q_RETURN_ARG(QVariantMap, *(new QVariantMap));
break;
default:
break;
}
bool success = m_adapted->metaObject()->invokeMethod(
m_adapted,
methodName.toLatin1().constData(),
Qt::DirectConnection,
returnValue,
arguments[0],
arguments[1],
arguments[2],
arguments[3],
arguments[4],
arguments[5],
arguments[6],
arguments[7],
arguments[8],
arguments[9]
);
// clean up memory allocation
for(int i = 0; i < parameterCount; ++i)
{
QVariant::Type parameterType = parameterList.value(i).type();
switch(parameterType)
{
case QVariant::Bool:
delete static_cast<bool*>(arguments[i].data());
break;
case QVariant::Int:
delete static_cast<int*>(arguments[i].data());
break;
case QVariant::String:
delete static_cast<QString*>(arguments[i].data());
break;
case QVariant::List:
delete static_cast<QVariantList*>(arguments[i].data());
break;
case QVariant::Map:
delete static_cast<QVariantMap*>(arguments[i].data());
break;
default:
break;
}
}
if(success == false)
{
ret.code = JsonRpc::InternalError;
ret.message = "Could not execute method.";
return ret;
}
ret.succeeded = true;
switch(returnType)
{
case QVariant::Bool:
ret.data = *static_cast<bool*>(returnValue.data());
break;
case QVariant::Int:
ret.data = *static_cast<int*>(returnValue.data());
break;
case QVariant::String:
ret.data = *static_cast<QString*>(returnValue.data());
break;
case QVariant::List:
ret.data = *static_cast<QVariantList*>(returnValue.data());
break;
case QVariant::Map:
ret.data = *static_cast<QVariantMap*>(returnValue.data());
break;
default:
break;
}
return ret;
}
void JsonRpcAdaptorPrivate::processJson(const QString& json)
{
m_jsonRpc.processJson(json);
}
}

View file

@ -0,0 +1,44 @@
#ifndef _JSONQT_JSON_RPC_ADAPTOR_PRIVATE_H
#define _JSONQT_JSON_RPC_ADAPTOR_PRIVATE_H
#include "JsonRpc.h"
#include <QMetaMethod>
#include <QObject>
#include <QStringList>
namespace JsonQt
{
class JsonRpcAdaptorPrivate : public QObject
{
Q_OBJECT
public:
JsonRpcAdaptorPrivate(QObject* adapt, QObject* parent);
signals:
void sendJson(const QString& json);
public slots:
void processJson(const QString& json);
private slots:
void requestReceived(const QVariant& id, const QString& method, const QVariant& parameters);
private:
struct ReturnData
{
bool succeeded;
int code;
QString message;
QVariant data;
};
void populateServiceDescription();
QString getClassInfo(const char* name);
ReturnData invokeMethod(const QString& method, const QVariant& parameters);
QMap<QString, QMetaMethod> m_methods;
QMap<QString, QMap<QString, int> > m_parameterIndices;
QVariantMap m_serviceDescription;
JsonRpc m_jsonRpc;
QObject* m_adapted;
};
}
#endif

View file

@ -0,0 +1,53 @@
/* LICENSE NOTICE
Copyright (c) 2008, Frederick Emmott <mail@fredemmott.co.uk>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "JsonToProperties.h"
#include "JsonToVariant.h"
#include <QDebug>
#include <QMetaObject>
#include <QMetaProperty>
namespace JsonQt
{
JsonToProperties::JsonToProperties()
{
}
void JsonToProperties::parse(const QString& json, QObject* object)
throw(ParseException)
{
QVariantMap dataMap = JsonToVariant::parse(json).toMap();
const QMetaObject* meta = object->metaObject();
for(
int i = 0;
i < meta->propertyCount();
++i
)
{
QMetaProperty property = meta->property(i);
if(dataMap.contains(property.name()))
{
QVariant data = dataMap[property.name()];
if(data.canConvert(property.type()))
property.write(object, data);
else
qDebug() << QObject::tr("Found property %1 with incompatible data type.").arg(property.name());
}
}
}
};

View file

@ -0,0 +1,52 @@
/* LICENSE NOTICE
Copyright (c) 2008, Frederick Emmott <mail@fredemmott.co.uk>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _JSONQT_JSON_TO_PROPERTIES_H
#define _JSONQT_JSON_TO_PROPERTIES_H
#include "ParseException.h"
#include "JsonQtExport.h"
#include <QObject>
#include <QString>
namespace JsonQt
{
/** Class for setting the properties of a QObject from a JSON string.
* Note that this only pays attention to basic types in the top level
* object in the JSON.
*
* @author Fred Emmott <mail@fredemmott.co.uk>
*/
class JSONQT_EXPORT JsonToProperties
{
public:
/** Main parsing function.
*
* @param json is a string containing JSON text.
* @param object is an object with properties to be
* filled from JSON.
* @throws ParseException if the string provided is not
* valid JSON (or at least this parser thinks it
* isn't ;) )
*/
static void parse(const QString& json, QObject* object)
throw(ParseException);
private:
JsonToProperties();
};
}
#endif

606
third-party/JsonQt/lib/JsonToVariant.cpp vendored Normal file
View file

@ -0,0 +1,606 @@
/* LICENSE NOTICE
Copyright (c) 2008, Frederick Emmott <mail@fredemmott.co.uk>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "JsonToVariant.h"
#include <QDebug>
#define FAIL(x) throw ParseException(*m_sym, x, remaining())
namespace JsonQt
{
JsonToVariant::JsonToVariant(){}
QVariant JsonToVariant::parse(const QString& json) throw(ParseException)
{
JsonToVariant parser;
// Store the start and end of the string
parser.m_next = json.constBegin();
parser.m_sym = parser.m_next;
parser.m_end = json.constEnd();
// Parse any JSON value.
return parser.parseValue();
}
QList<QVariantMap> JsonToVariant::multiParse(const QString& raw) throw(ParseException)
{
QList<QVariantMap> objects;
QString json(raw.trimmed());
JsonToVariant parser;
// Store the start and end of the string
parser.m_next = json.constBegin();
parser.m_sym = parser.m_next;
parser.m_end = json.constEnd();
// A JSON Object is the top-level item in the parse tree
do
{
objects.append(parser.parseObject());
}
while(parser.m_next != parser.m_end && parser.m_sym != parser.m_end);
return objects;
}
QVariantMap JsonToVariant::parseObject()
{
/*
* object
* {}
* { members }
*/
QVariantMap data;
consume('{');
if(peekNext() != '}')
data = parseMembers();
consume('}');
return data;
}
QVariantMap JsonToVariant::parseMembers()
{
/*
* members
* pair
* pair , members
*/
QVariantMap data;
QPair<QString, QVariant> pair;
// loop instead of recursing
do
{
// Grab a pair
pair = parsePair();
// Store it in our data
data[pair.first] = pair.second;
}
while(tryConsume(',')); // Loop if we've got a list separator
return data;
}
QPair<QString, QVariant> JsonToVariant::parsePair()
{
/*
* pair
* string : value
*/
QString key = parseString();
consume(':');
QVariant value = parseValue();
return qMakePair(key, value);
}
QVariantList JsonToVariant::parseArray()
{
/*
* array
* []
* [ elements ]
*/
QVariantList data;
consume('[');
if(peekNext() != ']')
data = parseElements();
consume(']');
return data;
}
QVariantList JsonToVariant::parseElements()
{
/*
* elements
* value
* value , elements
*/
QVariantList data;
// loop instead of recursing
do
{
// Grab a value
data += parseValue();
}
while(tryConsume(',')); // repeat if we've got a list separator
return data;
}
QVariant JsonToVariant::parseValue()
{
/*
* value
* string
* number
* object
* array
* bool
* null
*/
tryConsume(':');
// Lookahead to work out the type of value
switch(peekNext().toAscii())
{
case '"':
return parseString();
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '-':
return parseNumber();
case '{':
return parseObject();
case '[':
return parseArray();
case 't': // true
case 'f': // false
return parseBool();
case 'n': // null
return parseNull();
default:
FAIL(QObject::tr("string, number, object, array, bool, or null"));
}
}
QString JsonToVariant::parseString()
{
/*
* string
* ""
* " chars "
*/
QString data;
// Starting quotation marks
consume('"');
// If it's a non-empty string, grab the contents
if(*m_next != '"')
data = parseChars();
// Ending quotation marks
consume('"');
return data;
}
QString JsonToVariant::parseChars()
{
/*
* chars
* char
* char chars
*/
QString data;
// chars contains at least one char
data = parseChar();
while(peekNext() != '"')
data.append( parseChar() );
return data;
}
QChar JsonToVariant::parseChar()
{
/*
* char
* any character except for ", \, or control characters
* \"
* \\
* \/
* \b
* \f
* \n
* \r
* \t
* \u four-hex-digits
*/
// Grab the next character, without skipping whitespace
consume(false);
// We're not allowed unescaped quotation marks
if(*m_sym == '"')
FAIL(QObject::tr("Any unicode character except for \" or JSON escape sequences"));
// But some escape sequences are allowed
if(*m_sym == '\\')
{
QString digits;
switch(consume().toAscii())
{
case '"':
return '"';
case '\\':
return '\\';
case '/':
return '/';
case 'b':
return '\b';
case 'f':
return '\f';
case 'n':
return '\n';
case 'r':
return '\r';
case 't':
return '\t';
case 'u':
// Unicode 4-digit hex
for(int i = 0; i < 4; ++i)
{
digits += parseHexDigit();
}
return QChar(digits.toInt(0, 16));
default:
FAIL("[\"\\/bfnrtu]");
}
}
return *m_sym;
}
QVariant JsonToVariant::parseNumber()
{
/*
* number
* int
* int frac
* int exp
* int frac exp
*/
// Every JSON number starts with an int
QString data = parseInt();
// Lookahead for fractions and exponents
// Do we have a fraction?
if(*m_next == '.') data += parseFrac();
// Do we have an exponent?
if(*m_next == 'e' || *m_next == 'E') data += parseExp();
// Try several return types...
bool ok;
QVariant ret;
ret = data.toInt(&ok); if(ok) return ret;
ret = data.toLongLong(&ok); if(ok) return ret;
ret = data.toDouble(&ok); if(ok) return ret;
// If this point is reached, don't know how to convert the string
// to an integer.
Q_ASSERT(false);
return QVariant();
}
QString JsonToVariant::parseInt()
{
/*
* int
* digit
* digit1-9 digits
* - digit
* - digit1-9 digits
*/
QString data;
// Match any negation mark
if(tryConsume('-'))
data = "-";
// Grab the first digit...
QChar firstDigit = parseDigit();
data += firstDigit;
// ...if it's not zero...
if(firstDigit != '0')
{
// ... try and add more digits.
try { data += parseDigits(); }
catch(ParseException)
{
// Catch, as more digits are entirely optional
// Roll back.
m_next = m_sym--;
}
}
return data;
}
QString JsonToVariant::parseFrac()
{
/*
* frac
* . digits
*/
consume('.');
return QString(".%1").arg(parseDigits());
}
QString JsonToVariant::parseExp()
{
/*
* exp
* e digits
*/
QString data;
data = parseE();
data += parseDigits();
return data;
}
QString JsonToVariant::parseDigits()
{
/*
* digits
* digit
* digit digits
*/
QString data;
// Digits has at least one digit...
data += parseDigit();
// ... try and get some more
// Loop instead of recurse
Q_FOREVER
{
try { data += parseDigit(); }
catch(ParseException)
{
m_next = m_sym--; // roll back
break;
}
}
return data;
}
QString JsonToVariant::parseE()
{
/*
* e
* e
* e+
* e-
* E
* E+
* E-
*/
// Try and grab an 'e' or 'E'
if(consume(false).toLower() == 'e')
{
// digits in follow[e]
if(m_next->isDigit())
return "e";
// Hopefully the next is a + or -
// grab another chracter...
consume(false);
// If it's not + or -, fail
if(*m_sym != '+' && *m_sym != '-')
FAIL("+ | -");
// Otherwise, return e[+-]
return QString("e%1").arg(*m_sym);
}
else
FAIL("e | E");
}
QChar JsonToVariant::parseDigit()
{
/*
* digit
* [0-9]
*/
if(!consume(false).isDigit())
FAIL("[0-9]");
return *m_sym;
}
QChar JsonToVariant::parseHexDigit()
{
/*
* hexdigit
* [0-9a-fA-F]
*/
QChar character = consume().toLower();
if(character.isDigit() || (character >= 'a' && character <= 'f'))
return character;
FAIL("[0-9a-fA-F]");
}
bool JsonToVariant::parseBool()
{
/*
* bool
* true
* false
*/
switch(peekNext().toAscii())
{
case 't':
consume(QString("true"));
return true;
case 'f':
consume(QString("false"));
return false;
default:
consume(false);
FAIL("true | false");
}
}
QVariant JsonToVariant::parseNull()
{
/*
* null
* null
*/
consume(QString("null"));
return QVariant();
}
QString JsonToVariant::remaining()
{
QString data;
QString::ConstIterator it = m_sym;
while(it != m_end) data += *it++;
return data;
}
QChar JsonToVariant::consume(bool skipWhitespace) throw(ParseException)
{
// Read a character...
do
{
if(m_next == m_end)
{
throw ParseException("EOF", "symbol", remaining());
}
m_sym = m_next++;
}
//...and loop while we get whitespace, if it's being skipped
while(skipWhitespace && m_sym->isSpace());
// Just for convenience...
return *m_sym;
}
void JsonToVariant::consume(QChar wanted) throw(ParseException)
{
// Grab a char(ignoring whitespace), and if it's not what's
// expected, throw
if(consume() != wanted)
{
FAIL(wanted);
}
}
void JsonToVariant::consume(char wanted) throw(ParseException)
{
// Convenience function for the above
consume(QChar(wanted));
}
void JsonToVariant::consume(QString wanted) throw(ParseException)
{
// Keep track of where we start...
QString::ConstIterator it = m_sym;
// Grab wanted.length() characters, and compare them to the
// character in the appropriate position in the parameter
for(int i = 0; i < wanted.length(); ++i)
if(consume(false) != wanted[i])
{
// If it doesn't match, roll back, and throw a
// parse exception
m_sym = it;
m_next = ++it;
FAIL(wanted);
}
}
bool JsonToVariant::tryConsume(QChar wanted) throw()
{
// Grab the next character
try
{
consume();
}
catch(ParseException)
{
// End-Of-String, rollback and return false
m_next = m_sym--;
return false;
}
// Check if it's what we want
if(*m_sym != wanted)
{
// nope, something else, rollback and return false
m_next = m_sym--;
return false;
}
return true;
}
QChar JsonToVariant::peekNext(bool skipWhitespace) throw(ParseException)
{
QString::ConstIterator it = m_sym;
do
{
++it;
if(it == m_end)
{
FAIL("symbol");
}
}
while(skipWhitespace && it->isSpace());
return *it;
}
}

160
third-party/JsonQt/lib/JsonToVariant.h vendored Normal file
View file

@ -0,0 +1,160 @@
/* LICENSE NOTICE
Copyright (c) 2008, Frederick Emmott <mail@fredemmott.co.uk>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _JSONQT_JSON_TO_VARIANT_H
#define _JSONQT_JSON_TO_VARIANT_H
#include "ParseException.h"
#include "JsonQtExport.h"
#include <QList>
#include <QPair>
#include <QString>
#include <QVariant>
/** Qt-based JSON handling.
* This is based on a recursive descent parser with 1-character lookahed,
* and follows the structure of the grammar presented on json.org as closely
* as possible, to avoid mistakes, and hopefully to make the code more readable.
*
* @author Fred Emmott <mail@fredemmott.co.uk>
*/
namespace JsonQt
{
/** Class for converting JSON strings to QVariant-based structures.
*
* @author Fred Emmott <mail@fredemmott.co.uk>
*/
class JSONQT_EXPORT JsonToVariant
{
public:
/** Main parsing function.
*
* @param json is a string containing JSON text.
* @returns A QVariant-representation of the JSON
* structure.
* @throws ParseException if the string provided is not
* valid JSON (or at least this parser thinks it
* isn't ;) )
*/
static QVariant parse(const QString& json) throw (ParseException);
/** Parse multiple objects in one string.
* This is useful when working on streams where
* one-chunk-per-json-object is not guaranteed.
*/
static QList<QVariantMap> multiParse(const QString& json) throw(ParseException);
private:
JsonToVariant();
// Parsers for types given on JSON.org
QVariantMap parseObject();
QVariantMap parseMembers();
QPair<QString, QVariant> parsePair();
QVariantList parseArray();
QVariantList parseElements();
QVariant parseValue();
QString parseString();
QString parseChars();
QChar parseChar();
QVariant parseNumber();
QString parseInt();
QString parseFrac();
QString parseExp();
QString parseDigits();
QString parseE();
// Parsers for types implied on JSON.org
QChar parseDigit();
QChar parseHexDigit();
bool parseBool();
QVariant parseNull();
// Internal functions
/// The unparsed part of the input string.
inline QString remaining();
/** Consume the next character.
* Advances m_sym to the next character, and returns it.
* Optionally skips over whitespace.
*
* @param skipWhitespace controls if whitespace is
* ignored.
* @returns *m_sym
* @throws ParseException if the end of the string is
* reached.
*/
QChar consume(bool skipWhitespace = true)
throw(ParseException);
/** Consume the next character, and check for equality
* with the specified character.
*
* @param wanted is the character to compare to.
* @throws ParseException if the end of the string is
* reached, or the characaters are not equal.
*/
void consume(QChar wanted) throw(ParseException);
/// Convenience function for consume(QChar).
void consume(char wanted) throw(ParseException);
/** Attempt to consume the specified string.
* This attempts to consume length(wanted) characters,
* including whitespace, and checks that they are equal
* to the characters in the same position in the
* specified string.
*
* @param wanted is the string to attempt to consume.
* @throws ParseException if the end of the string is
* reached, or the string comparisson fails.
*/
void consume(QString wanted) throw(ParseException);
/** Try to consume a single character, without throw.
* This will try to read a single character, and
* compares to the specified character.
*
* @param wanted is the character to compare to.
* @returns true if the character specified was
* successfully consumed.
* @returns false if the end of the string was reached,
* or the characters were not equal.
*/
bool tryConsume(QChar wanted) throw();
/** Return the next symbol.
* Optionally skips whitespace.
*
* @param skipWhitespace sets the whitespace handling.
* @returns the next symbol.
* @throws ParseException if the end of the string is
* reached.
*/
QChar peekNext(bool skipWhitespace = true)
throw(ParseException);
// Variables
/// Iterator pointing at the current symbol.
QString::ConstIterator m_sym;
/// Iterator pointing at the next symbol.
QString::ConstIterator m_next;
/// Iterator pointing at the end of the string.
QString::ConstIterator m_end;
};
}
#endif

View file

@ -0,0 +1,47 @@
/* LICENSE NOTICE
Copyright (c) 2008, Frederick Emmott <mail@fredemmott.co.uk>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "ParseException.h"
// For QObject::tr
#include <QObject>
#include "psilogger.h"
namespace JsonQt
{
ParseException::ParseException(const QString& got, const QString& expected, const QString& remaining) throw()
:
m_got(got),
m_expected(expected),
m_remaining(remaining)
{
PsiLogger::instance()->log(QString("JsonQt::ParseException(): got = %1; expected = %2; remaining = %3")
.arg(got)
.arg(expected)
.arg(remaining));
}
ParseException::~ParseException() throw(){}
const char* ParseException::what() const throw()
{
return qPrintable(QObject::tr("A parsing error occurred:\n\tGot: '%1'\n\tExpected: '%2'\n\tAt: '%3'").arg(m_got).arg(m_expected).arg(m_remaining));
}
QString ParseException::got() { return m_got; }
QString ParseException::expected() { return m_expected; }
QString ParseException::remaining() { return m_remaining; }
}

63
third-party/JsonQt/lib/ParseException.h vendored Normal file
View file

@ -0,0 +1,63 @@
/* LICENSE NOTICE
Copyright (c) 2008, Frederick Emmott <mail@fredemmott.co.uk>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _JSONQT_PARSE_EXCEPTION_H
#define _JSONQT_PARSE_EXCEPTION_H
#include "JsonQtExport.h"
#include <exception>
#include <QChar>
#include <QString>
namespace JsonQt
{
/** Parsing exception class.
* Raised whenever JsonQt can't pass something it's been given, for
* whatever reason.
*/
class JSONQT_EXPORT ParseException : public std::exception
{
public:
/** Create a ParseException.
* @param got is what was found in the string.
* @param expected is what the parser was expecting.
* @param remaining is what was left of the input.
*/
ParseException(
const QString& got,
const QString& expected,
const QString& remaining
) throw();
~ParseException() throw();
/// A single string providing information on the
/// exception.
virtual const char* what() const throw();
/// What the parser found.
QString got();
/// What the parser was expecting.
QString expected();
/// The remaining unparsed input.
QString remaining();
private:
QString m_got;
QString m_expected;
QString m_remaining;
};
};
#endif

View file

@ -0,0 +1,64 @@
#include "VariantToJson.h"
namespace JsonQt
{
QString VariantToJson::parse(const QVariantMap& data)
{
QStringList members;
for(QVariantMap::ConstIterator it = data.begin(); it != data.end(); ++it)
{
members.append(QString("\"%1\": %2").arg(it.key()).arg(parseElement(it.value())));
}
return "{" + members.join(", ") + "}";
}
QString VariantToJson::parseElement(const QVariant& value)
{
switch(value.type())
{
case QVariant::Bool:
return value.toBool() ? "true" : "false";
case QVariant::Map:
return parse(value.toMap());
case QVariant::Int:
return QString::number(value.toInt());
case QVariant::LongLong:
return QString::number(value.toLongLong());
case QVariant::Double:
return QString::number(value.toDouble());
case QVariant::UInt:
return QString::number(value.toUInt());
case QVariant::ULongLong:
return QString::number(value.toULongLong());
case QVariant::List:
return parseList(value.toList());
case QVariant::String:
return QString("\"%1\"").arg(value.toString().replace("\\", "\\\\").replace("\"", "\\\""));
case QVariant::StringList:
return parseStringList(value.toStringList());
case QVariant::Invalid:
return "null";
default:
return QString();
}
}
QString VariantToJson::parseList(const QVariantList& list)
{
QStringList parts;
Q_FOREACH(QVariant variant, list)
{
parts.append(parseElement(variant));
}
return "[" + parts.join(", ") + "]";
}
QString VariantToJson::parseStringList(const QStringList& stringList)
{
QVariantList variantList;
Q_FOREACH(const QString& string, stringList)
{
variantList.append(string);
}
return parseList(variantList);
}
}

40
third-party/JsonQt/lib/VariantToJson.h vendored Normal file
View file

@ -0,0 +1,40 @@
#ifndef _JSONQT_VARIANT_TO_JSON_H
#define _JSONQT_VARIANT_TO_JSON_H
#include "JsonQtExport.h"
#include <QString>
#include <QStringList>
#include <QVariant>
namespace JsonQt
{
/** Class for converting QVariants into JSON structures.
*
* The following variant types are supported:
* - QVariant::Bool
* - QVariant::String
* - QVariant::Double
* - QVariant::Int
* - QVariant::LongLong
* - QVariant::UInt
* - QVariant::ULongLong
* - QVariant::Invalid
* - QVariant::List // JSON array
* - QVariant::Map // JSON object
*
* @author Fred Emmott <mail@fredemmott.co.uk>
*/
class JSONQT_EXPORT VariantToJson
{
public:
/// Parse a QVariant into JSON.
static QString parse(const QVariantMap& data);
private:
static QString parseElement(const QVariant& element);
static QString parseList(const QVariantList& list);
static QString parseStringList(const QStringList& list);
};
}
#endif