QJson: update to 5e3b9b84b225f4612e09ef05aa6d8c23379e4e71

This commit is contained in:
Chocobo1
2016-11-04 01:33:25 +08:00
committed by sledgehammer999
parent 1c1917f885
commit 89bd0e4397
5 changed files with 176 additions and 147 deletions

View File

@@ -2,6 +2,7 @@
*
* Copyright (C) 2009 Till Adam <adam@kde.org>
* Copyright (C) 2009 Flavio Castelli <flavio@castelli.name>
* Copyright (C) 2016 Anton Kudryavtsev <a.kudryavtsev@netris.ru>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -24,7 +25,12 @@
#include <QtCore/QStringList>
#include <QtCore/QVariant>
#include <cmath>
// cmath does #undef for isnan and isinf macroses what can be defined in math.h
#if defined(Q_OS_SYMBIAN) || defined(Q_OS_ANDROID) || defined(Q_OS_BLACKBERRY) || defined(Q_OS_SOLARIS)
# include <math.h>
#else
# include <cmath>
#endif
#ifdef Q_OS_SOLARIS
# ifndef isinf
@@ -51,10 +57,13 @@ class Serializer::SerializerPrivate {
bool specialNumbersAllowed;
IndentMode indentMode;
int doublePrecision;
QByteArray buildIndent(int spaces);
QByteArray serialize( const QVariant &v, bool *ok, int indentLevel = 0);
QString sanitizeString( QString str );
QByteArray join( const QList<QByteArray>& list, const QByteArray& sep );
static QByteArray buildIndent(int spaces);
static QByteArray escapeString( const QString& str );
static QByteArray join( const QList<QByteArray>& list, const QByteArray& sep );
static QByteArray join( const QList<QByteArray>& list, char sep );
};
QByteArray Serializer::SerializerPrivate::join( const QList<QByteArray>& list, const QByteArray& sep ) {
@@ -67,13 +76,24 @@ QByteArray Serializer::SerializerPrivate::join( const QList<QByteArray>& list, c
return res;
}
QByteArray Serializer::SerializerPrivate::join( const QList<QByteArray>& list, char sep ) {
QByteArray res;
Q_FOREACH( const QByteArray& i, list ) {
if ( !res.isEmpty() )
res += sep;
res += i;
}
return res;
}
QByteArray Serializer::SerializerPrivate::serialize( const QVariant &v, bool *ok, int indentLevel)
{
QByteArray str;
const QVariant::Type type = v.type();
if ( ! v.isValid() ) { // invalid or null?
str = "null";
} else if (( v.type() == QVariant::List ) || ( v.type() == QVariant::StringList )){ // an array or a stringlist?
} else if (( type == QVariant::List ) || ( type == QVariant::StringList )) { // an array or a stringlist?
const QVariantList list = v.toList();
QList<QByteArray> values;
Q_FOREACH( const QVariant& var, list )
@@ -101,22 +121,21 @@ QByteArray Serializer::SerializerPrivate::serialize( const QVariant &v, bool *ok
if (indentMode == QJson::IndentMedium || indentMode == QJson::IndentFull ) {
QByteArray indent = buildIndent(indentLevel);
str = indent + "[\n" + join( values, ",\n" ) + "\n" + indent + "]";
str = indent + "[\n" + join( values, ",\n" ) + '\n' + indent + ']';
}
else if (indentMode == QJson::IndentMinimum) {
QByteArray indent = buildIndent(indentLevel);
str = indent + "[\n" + join( values, ",\n" ) + "\n" + indent + "]";
str = indent + "[\n" + join( values, ",\n" ) + '\n' + indent + ']';
}
else if (indentMode == QJson::IndentCompact) {
str = "[" + join( values, "," ) + "]";
str = '[' + join( values, "," ) + ']';
}
else {
str = "[ " + join( values, ", " ) + " ]";
}
} else if ( v.type() == QVariant::Map ) { // variant is a map?
} else if ( type == QVariant::Map ) { // variant is a map?
const QVariantMap vmap = v.toMap();
QMapIterator<QString, QVariant> it( vmap );
if (indentMode == QJson::IndentMinimum) {
QByteArray indent = buildIndent(indentLevel);
@@ -135,18 +154,17 @@ QByteArray Serializer::SerializerPrivate::serialize( const QVariant &v, bool *ok
}
QList<QByteArray> pairs;
while ( it.hasNext() ) {
it.next();
for (QVariantMap::const_iterator it = vmap.begin(), end = vmap.end(); it != end; ++it) {
indentLevel++;
QByteArray serializedValue = serialize( it.value(), ok, indentLevel);
indentLevel--;
if ( !*ok ) {
break;
}
QByteArray key = sanitizeString( it.key() ).toUtf8();
QByteArray key = escapeString( it.key() );
QByteArray value = serializedValue.trimmed();
if (indentMode == QJson::IndentCompact) {
pairs << key + ":" + value;
pairs << key + ':' + value;
} else {
pairs << key + " : " + value;
}
@@ -157,7 +175,7 @@ QByteArray Serializer::SerializerPrivate::serialize( const QVariant &v, bool *ok
str += join( pairs, ",\n" + indent);
}
else if (indentMode == QJson::IndentCompact) {
str += join( pairs, "," );
str += join( pairs, ',' );
}
else {
str += join( pairs, ", " );
@@ -165,18 +183,17 @@ QByteArray Serializer::SerializerPrivate::serialize( const QVariant &v, bool *ok
if (indentMode == QJson::IndentMedium || indentMode == QJson::IndentFull) {
QByteArray indent = buildIndent(indentLevel);
str += "\n" + indent + "}";
str += '\n' + indent + '}';
}
else if (indentMode == QJson::IndentCompact) {
str += "}";
str += '}';
}
else {
str += " }";
}
} else if ( v.type() == QVariant::Hash ) { // variant is a hash?
} else if ( type == QVariant::Hash ) { // variant is a hash?
const QVariantHash vhash = v.toHash();
QHashIterator<QString, QVariant> it( vhash );
if (indentMode == QJson::IndentMinimum) {
QByteArray indent = buildIndent(indentLevel);
@@ -195,18 +212,16 @@ QByteArray Serializer::SerializerPrivate::serialize( const QVariant &v, bool *ok
}
QList<QByteArray> pairs;
while ( it.hasNext() ) {
it.next();
for (QVariantHash::const_iterator it = vhash.begin(), end = vhash.end(); it != end; ++it) {
QByteArray serializedValue = serialize( it.value(), ok, indentLevel + 1);
if ( !*ok ) {
break;
}
QByteArray key = sanitizeString( it.key() ).toUtf8();
QByteArray key = escapeString( it.key() );
QByteArray value = serializedValue.trimmed();
if (indentMode == QJson::IndentCompact) {
pairs << key + ":" + value;
pairs << key + ':' + value;
} else {
pairs << key + " : " + value;
}
@@ -217,7 +232,7 @@ QByteArray Serializer::SerializerPrivate::serialize( const QVariant &v, bool *ok
str += join( pairs, ",\n" + indent);
}
else if (indentMode == QJson::IndentCompact) {
str += join( pairs, "," );
str += join( pairs, ',' );
}
else {
str += join( pairs, ", " );
@@ -225,10 +240,10 @@ QByteArray Serializer::SerializerPrivate::serialize( const QVariant &v, bool *ok
if (indentMode == QJson::IndentMedium || indentMode == QJson::IndentFull) {
QByteArray indent = buildIndent(indentLevel);
str += "\n" + indent + "}";
str += '\n' + indent + '}';
}
else if (indentMode == QJson::IndentCompact) {
str += "}";
str += '}';
}
else {
str += " }";
@@ -248,9 +263,9 @@ QByteArray Serializer::SerializerPrivate::serialize( const QVariant &v, bool *ok
break;
}
if (( v.type() == QVariant::String ) || ( v.type() == QVariant::ByteArray )) { // a string or a byte array?
str = sanitizeString( v.toString() ).toUtf8();
} else if (( v.type() == QVariant::Double) || ((QMetaType::Type)v.type() == QMetaType::Float)) { // a double or a float?
if (( type == QVariant::String ) || ( type == QVariant::ByteArray )) { // a string or a byte array?
str += escapeString( v.toString() );
} else if (( type == QVariant::Double) || ((QMetaType::Type)type == QMetaType::Float)) { // a double or a float?
const double value = v.toDouble();
#if defined _WIN32 && !defined(Q_OS_SYMBIAN)
const bool special = _isnan(value) || !_finite(value);
@@ -281,15 +296,15 @@ QByteArray Serializer::SerializerPrivate::serialize( const QVariant &v, bool *ok
}
} else {
str = QByteArray::number( value , 'g', doublePrecision);
if( ! str.contains( "." ) && ! str.contains( "e" ) ) {
if( !str.contains( '.' ) && !str.contains( 'e' ) ) {
str += ".0";
}
}
} else if ( v.type() == QVariant::Bool ) { // boolean value?
} else if ( type == QVariant::Bool ) { // boolean value?
str += ( v.toBool() ? "true" : "false" );
} else if ( v.type() == QVariant::ULongLong ) { // large unsigned number?
} else if ( type == QVariant::ULongLong ) { // large unsigned number?
str += QByteArray::number( v.value<qulonglong>() );
} else if ( v.type() == QVariant::UInt ) { // unsigned int number?
} else if ( type == QVariant::UInt ) { // unsigned int number?
str += QByteArray::number( v.value<quint32>() );
} else if ( v.canConvert<qlonglong>() ) { // any signed number?
str += QByteArray::number( v.value<qlonglong>() );
@@ -297,7 +312,7 @@ QByteArray Serializer::SerializerPrivate::serialize( const QVariant &v, bool *ok
str += QByteArray::number( v.value<int>() );
} else if ( v.canConvert<QString>() ){ // can value be converted to string?
// this will catch QDate, QDateTime, QUrl, ...
str += sanitizeString( v.toString() ).toUtf8();
str += escapeString( v.toString() );
//TODO: catch other values like QImage, QRect, ...
} else {
*ok = false;
@@ -323,42 +338,52 @@ QByteArray Serializer::SerializerPrivate::buildIndent(int spaces)
spaces = 0;
}
for (int i = 0; i < spaces; i++ ) {
indent += " ";
indent += ' ';
}
return indent;
}
QString Serializer::SerializerPrivate::sanitizeString( QString str )
QByteArray Serializer::SerializerPrivate::escapeString( const QString& str )
{
str.replace( QLatin1String( "\\" ), QLatin1String( "\\\\" ) );
// escape unicode chars
QString result;
const ushort* unicode = str.utf16();
unsigned int i = 0;
while ( unicode[ i ] ) {
if ( unicode[ i ] < 128 ) {
result.append( QChar( unicode[ i ] ) );
QByteArray result;
result.reserve(str.size() + 2);
result.append('\"');
for (QString::const_iterator it = str.begin(), end = str.end(); it != end; ++it) {
ushort unicode = it->unicode();
switch ( unicode ) {
case '\"':
result.append("\\\"");
break;
case '\\':
result.append("\\\\");
break;
case '\b':
result.append("\\b");
break;
case '\f':
result.append("\\f");
break;
case '\n':
result.append("\\n");
break;
case '\r':
result.append("\\r");
break;
case '\t':
result.append("\\t");
break;
default:
if ( unicode > 0x1F && unicode < 128 ) {
result.append(static_cast<char>(unicode));
} else {
char escaped[7];
qsnprintf(escaped, sizeof(escaped)/sizeof(char), "\\u%04x", unicode);
result.append(escaped);
}
}
else {
QString hexCode = QString::number( unicode[ i ], 16 ).rightJustified( 4,
QLatin1Char('0') );
result.append( QLatin1String ("\\u") ).append( hexCode );
}
++i;
}
str = result;
str.replace( QLatin1String( "\"" ), QLatin1String( "\\\"" ) );
str.replace( QLatin1String( "\b" ), QLatin1String( "\\b" ) );
str.replace( QLatin1String( "\f" ), QLatin1String( "\\f" ) );
str.replace( QLatin1String( "\n" ), QLatin1String( "\\n" ) );
str.replace( QLatin1String( "\r" ), QLatin1String( "\\r" ) );
str.replace( QLatin1String( "\t" ), QLatin1String( "\\t" ) );
return QString( QLatin1String( "\"%1\"" ) ).arg( str );
result.append('\"');
return result;
}
Serializer::Serializer()