initial commit
This commit is contained in:
commit
9d20827c46
2469 changed files with 470994 additions and 0 deletions
76
third-party/JsonQt/lib/CMakeLists.txt
vendored
Normal file
76
third-party/JsonQt/lib/CMakeLists.txt
vendored
Normal 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
24
third-party/JsonQt/lib/JsonQtExport.h
vendored
Normal 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
167
third-party/JsonQt/lib/JsonRpc.cpp
vendored
Normal 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
105
third-party/JsonQt/lib/JsonRpc.h
vendored
Normal 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
|
||||
19
third-party/JsonQt/lib/JsonRpcAdaptor.cpp
vendored
Normal file
19
third-party/JsonQt/lib/JsonRpcAdaptor.cpp
vendored
Normal 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
69
third-party/JsonQt/lib/JsonRpcAdaptor.h
vendored
Normal 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
|
||||
351
third-party/JsonQt/lib/JsonRpcAdaptorPrivate.cpp
vendored
Normal file
351
third-party/JsonQt/lib/JsonRpcAdaptorPrivate.cpp
vendored
Normal 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);
|
||||
}
|
||||
}
|
||||
44
third-party/JsonQt/lib/JsonRpcAdaptorPrivate.h
vendored
Normal file
44
third-party/JsonQt/lib/JsonRpcAdaptorPrivate.h
vendored
Normal 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
|
||||
53
third-party/JsonQt/lib/JsonToProperties.cpp
vendored
Normal file
53
third-party/JsonQt/lib/JsonToProperties.cpp
vendored
Normal 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
52
third-party/JsonQt/lib/JsonToProperties.h
vendored
Normal file
52
third-party/JsonQt/lib/JsonToProperties.h
vendored
Normal 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
606
third-party/JsonQt/lib/JsonToVariant.cpp
vendored
Normal 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
160
third-party/JsonQt/lib/JsonToVariant.h
vendored
Normal 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
|
||||
47
third-party/JsonQt/lib/ParseException.cpp
vendored
Normal file
47
third-party/JsonQt/lib/ParseException.cpp
vendored
Normal 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
63
third-party/JsonQt/lib/ParseException.h
vendored
Normal 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
|
||||
64
third-party/JsonQt/lib/VariantToJson.cpp
vendored
Normal file
64
third-party/JsonQt/lib/VariantToJson.cpp
vendored
Normal 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
40
third-party/JsonQt/lib/VariantToJson.h
vendored
Normal 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
|
||||
Reference in a new issue