QJson project page QJson home page

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 }

SourceForge Logo hosts this site. Send comments to:
QJson Developers