]> git.cworth.org Git - apitrace/blob - thirdparty/qjson/serializer.cpp
Bundle QJSON sources.
[apitrace] / thirdparty / qjson / serializer.cpp
1 /* This file is part of qjson
2   *
3   * Copyright (C) 2009 Till Adam <adam@kde.org>
4   * Copyright (C) 2009 Flavio Castelli <flavio@castelli.name>
5   *
6   * This library is free software; you can redistribute it and/or
7   * modify it under the terms of the GNU Library General Public
8   * License as published by the Free Software Foundation; either
9   * version 2 of the License, or (at your option) any later version.
10   *
11   * This library is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   * Library General Public License for more details.
15   *
16   * You should have received a copy of the GNU Library General Public License
17   * along with this library; see the file COPYING.LIB.  If not, write to
18   * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19   * Boston, MA 02110-1301, USA.
20   */
21
22 #include "serializer.h"
23
24 #include <QtCore/QDataStream>
25 #include <QtCore/QStringList>
26 #include <QtCore/QVariant>
27
28 using namespace QJson;
29
30 class Serializer::SerializerPrivate {
31 };
32
33 Serializer::Serializer() : d( new SerializerPrivate ) {
34 }
35
36 Serializer::~Serializer() {
37   delete d;
38 }
39
40 void Serializer::serialize( const QVariant& v, QIODevice* io, bool* ok )
41 {
42   Q_ASSERT( io );
43   if (!io->isOpen()) {
44     if (!io->open(QIODevice::WriteOnly)) {
45       if ( ok != 0 )
46         *ok = false;
47       qCritical ("Error opening device");
48       return;
49     }
50   }
51
52   if (!io->isWritable()) {
53     if (ok != 0)
54       *ok = false;
55     qCritical ("Device is not readable");
56     io->close();
57     return;
58   }
59
60   const QByteArray str = serialize( v );
61   if ( !str.isNull() ) {
62     QDataStream stream( io );
63     stream << str;
64   } else {
65     if ( ok )
66       *ok = false;
67   }
68 }
69
70 static QString sanitizeString( QString str )
71 {
72   str.replace( QLatin1String( "\\" ), QLatin1String( "\\\\" ) );
73   str.replace( QLatin1String( "\"" ), QLatin1String( "\\\"" ) );
74   str.replace( QLatin1String( "\b" ), QLatin1String( "\\b" ) );
75   str.replace( QLatin1String( "\f" ), QLatin1String( "\\f" ) );
76   str.replace( QLatin1String( "\n" ), QLatin1String( "\\n" ) );
77   str.replace( QLatin1String( "\r" ), QLatin1String( "\\r" ) );
78   str.replace( QLatin1String( "\t" ), QLatin1String( "\\t" ) );
79   return QString( QLatin1String( "\"%1\"" ) ).arg( str );
80 }
81
82 static QByteArray join( const QList<QByteArray>& list, const QByteArray& sep ) {
83   QByteArray res;
84   Q_FOREACH( const QByteArray& i, list ) {
85     if ( !res.isEmpty() )
86       res += sep;
87     res += i;
88   }
89   return res;
90 }
91
92 QByteArray Serializer::serialize( const QVariant &v )
93 {
94   QByteArray str;
95   bool error = false;
96
97   if ( ! v.isValid() ) { // invalid or null?
98     str = "null";
99   } else if ( v.type() == QVariant::List ) { // variant is a list?
100     const QVariantList list = v.toList();
101     QList<QByteArray> values;
102     Q_FOREACH( const QVariant& v, list )
103     {
104       QByteArray serializedValue = serialize( v );
105       if ( serializedValue.isNull() ) {
106         error = true;
107         break;
108       }
109       values << serializedValue;
110     }
111     str = "[ " + join( values, ", " ) + " ]";
112   } else if ( v.type() == QVariant::Map ) { // variant is a map?
113     const QVariantMap vmap = v.toMap();
114     QMapIterator<QString, QVariant> it( vmap );
115     str = "{ ";
116     QList<QByteArray> pairs;
117     while ( it.hasNext() ) {
118       it.next();
119       QByteArray serializedValue = serialize( it.value() );
120       if ( serializedValue.isNull() ) {
121         error = true;
122         break;
123       }
124       pairs << sanitizeString( it.key() ).toUtf8() + " : " + serializedValue;
125     }
126     str += join( pairs, ", " );
127     str += " }";
128   } else if (( v.type() == QVariant::String ) ||  ( v.type() == QVariant::ByteArray )) { // a string or a byte array?
129     str = sanitizeString( v.toString() ).toUtf8();
130   } else if ( v.type() == QVariant::Double ) { // a double?
131     str = QByteArray::number( v.toDouble() );
132     if( ! str.contains( "." ) && ! str.contains( "e" ) ) {
133       str += ".0";
134     }
135   } else if ( v.type() == QVariant::Bool ) { // boolean value?
136     str = ( v.toBool() ? "true" : "false" );
137   } else if ( v.type() == QVariant::ULongLong ) { // large unsigned number?
138     str = QByteArray::number( v.value<qulonglong>() );
139   } else if ( v.canConvert<qlonglong>() ) { // any signed number?
140     str = QByteArray::number( v.value<qlonglong>() );
141   } else if ( v.canConvert<QString>() ){ // can value be converted to string?
142     // this will catch QDate, QDateTime, QUrl, ...
143     str = sanitizeString( v.toString() ).toUtf8();
144     //TODO: catch other values like QImage, QRect, ...
145   } else {
146     error = true;
147   }
148   if ( !error )
149     return str;
150   else
151     return QByteArray();
152 }