QJson project page QJson home page

/builddir/build/BUILD/qjson/src/serializer.cpp
00001 /* This file is part of qjson
00002   *
00003   * Copyright (C) 2009 Till Adam <adam@kde.org>
00004   * Copyright (C) 2009 Flavio Castelli <flavio@castelli.name>
00005   *
00006   * This library is free software; you can redistribute it and/or
00007   * modify it under the terms of the GNU Library General Public
00008   * License as published by the Free Software Foundation; either
00009   * version 2 of the License, or (at your option) any later version.
00010   *
00011   * This library is distributed in the hope that it will be useful,
00012   * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014   * Library General Public License for more details.
00015   *
00016   * You should have received a copy of the GNU Library General Public License
00017   * along with this library; see the file COPYING.LIB.  If not, write to
00018   * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019   * Boston, MA 02110-1301, USA.
00020   */
00021 
00022 #include "serializer.h"
00023 
00024 #include <QtCore/QDataStream>
00025 #include <QtCore/QStringList>
00026 #include <QtCore/QVariant>
00027 
00028 using namespace QJson;
00029 
00030 class Serializer::SerializerPrivate {
00031 };
00032 
00033 Serializer::Serializer() : d( new SerializerPrivate ) {
00034 }
00035 
00036 Serializer::~Serializer() {
00037   delete d;
00038 }
00039 
00040 void Serializer::serialize( const QVariant& v, QIODevice* io, bool* ok )
00041 {
00042   Q_ASSERT( io );
00043   if (!io->isOpen()) {
00044     if (!io->open(QIODevice::WriteOnly)) {
00045       if ( ok != 0 )
00046         *ok = false;
00047       qCritical ("Error opening device");
00048       return;
00049     }
00050   }
00051 
00052   if (!io->isWritable()) {
00053     if (ok != 0)
00054       *ok = false;
00055     qCritical ("Device is not readable");
00056     io->close();
00057     return;
00058   }
00059 
00060   const QByteArray str = serialize( v );
00061   if ( !str.isNull() ) {
00062     QDataStream stream( io );
00063     stream << str;
00064   } else {
00065     if ( ok )
00066       *ok = false;
00067   }
00068 }
00069 
00070 static QString sanitizeString( QString str )
00071 {
00072   str.replace( QLatin1String( "\\" ), QLatin1String( "\\\\" ) );
00073   str.replace( QLatin1String( "\"" ), QLatin1String( "\\\"" ) );
00074   str.replace( QLatin1String( "\b" ), QLatin1String( "\\b" ) );
00075   str.replace( QLatin1String( "\f" ), QLatin1String( "\\f" ) );
00076   str.replace( QLatin1String( "\n" ), QLatin1String( "\\n" ) );
00077   str.replace( QLatin1String( "\r" ), QLatin1String( "\\r" ) );
00078   str.replace( QLatin1String( "\t" ), QLatin1String( "\\t" ) );
00079   return QString( QLatin1String( "\"%1\"" ) ).arg( str );
00080 }
00081 
00082 static QByteArray join( const QList<QByteArray>& list, const QByteArray& sep ) {
00083   QByteArray res;
00084   Q_FOREACH( const QByteArray& i, list ) {
00085     if ( !res.isEmpty() )
00086       res += sep;
00087     res += i;
00088   }
00089   return res;
00090 }
00091 
00092 QByteArray Serializer::serialize( const QVariant &v )
00093 {
00094   QByteArray str;
00095   bool error = false;
00096 
00097   if ( ! v.isValid() ) { // invalid or null?
00098     str = "null";
00099   } else if ( v.type() == QVariant::List ) { // variant is a list?
00100     const QVariantList list = v.toList();
00101     QList<QByteArray> values;
00102     Q_FOREACH( const QVariant& v, list )
00103     {
00104       QByteArray serializedValue = serialize( v );
00105       if ( serializedValue.isNull() ) {
00106         error = true;
00107         break;
00108       }
00109       values << serializedValue;
00110     }
00111     str = "[ " + join( values, ", " ) + " ]";
00112   } else if ( v.type() == QVariant::Map ) { // variant is a map?
00113     const QVariantMap vmap = v.toMap();
00114     QMapIterator<QString, QVariant> it( vmap );
00115     str = "{ ";
00116     QList<QByteArray> pairs;
00117     while ( it.hasNext() ) {
00118       it.next();
00119       QByteArray serializedValue = serialize( it.value() );
00120       if ( serializedValue.isNull() ) {
00121         error = true;
00122         break;
00123       }
00124       pairs << sanitizeString( it.key() ).toUtf8() + " : " + serializedValue;
00125     }
00126     str += join( pairs, ", " );
00127     str += " }";
00128   } else if (( v.type() == QVariant::String ) ||  ( v.type() == QVariant::ByteArray )) { // a string or a byte array?
00129     str = sanitizeString( v.toString() ).toUtf8();
00130   } else if ( v.type() == QVariant::Double ) { // a double?
00131     str = QByteArray::number( v.toDouble() );
00132     if( ! str.contains( "." ) && ! str.contains( "e" ) ) {
00133       str += ".0";
00134     }
00135   } else if ( v.type() == QVariant::Bool ) { // boolean value?
00136     str = ( v.toBool() ? "true" : "false" );
00137   } else if ( v.type() == QVariant::ULongLong ) { // large unsigned number?
00138     str = QByteArray::number( v.value<qulonglong>() );
00139   } else if ( v.canConvert<qlonglong>() ) { // any signed number?
00140     str = QByteArray::number( v.value<qlonglong>() );
00141   } else if ( v.canConvert<QString>() ){ // can value be converted to string?
00142     // this will catch QDate, QDateTime, QUrl, ...
00143     str = sanitizeString( v.toString() ).toUtf8();
00144     //TODO: catch other values like QImage, QRect, ...
00145   } else {
00146     error = true;
00147   }
00148   if ( !error )
00149     return str;
00150   else
00151     return QByteArray();
00152 }

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