smf/smfservermodule/util/qjson/src/serializer.cpp
changeset 10 1d94eb8df9c2
parent 9 b85b0c039c14
equal deleted inserted replaced
9:b85b0c039c14 10:1d94eb8df9c2
     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 }