diff --git a/src/webui/qjson/json_parser.cc b/src/webui/qjson/json_parser.cc index 84fdfac73..5c1788f2e 100644 --- a/src/webui/qjson/json_parser.cc +++ b/src/webui/qjson/json_parser.cc @@ -149,7 +149,7 @@ namespace yy { { if (*yystr == '"') { - std::string yyr = ""; + std::string yyr; char const *yyp = yystr; for (;;) @@ -471,17 +471,17 @@ namespace yy { } break; - case 6: + case 5: /* Line 670 of lalr1.cc */ -#line 96 "json_parser.yy" +#line 95 "json_parser.yy" { (yyval) = QVariant(QVariantMap()); } break; - case 7: + case 6: /* Line 670 of lalr1.cc */ -#line 99 "json_parser.yy" +#line 98 "json_parser.yy" { QVariantMap* map = (yysemantic_stack_[(3) - (2)]).value(); (yyval) = QVariant(*map); @@ -489,9 +489,9 @@ namespace yy { } break; - case 8: + case 7: /* Line 670 of lalr1.cc */ -#line 105 "json_parser.yy" +#line 104 "json_parser.yy" { QVariantMap* pair = new QVariantMap(); pair->insert((yysemantic_stack_[(3) - (1)]).toString(), (yysemantic_stack_[(3) - (3)])); @@ -499,25 +499,25 @@ namespace yy { } break; - case 9: + case 8: /* Line 670 of lalr1.cc */ -#line 110 "json_parser.yy" +#line 109 "json_parser.yy" { (yyval).value()->insert((yysemantic_stack_[(5) - (3)]).toString(), (yysemantic_stack_[(5) - (5)])); } break; - case 10: + case 9: /* Line 670 of lalr1.cc */ -#line 114 "json_parser.yy" +#line 113 "json_parser.yy" { (yyval) = QVariant(QVariantList()); } break; - case 11: + case 10: /* Line 670 of lalr1.cc */ -#line 117 "json_parser.yy" +#line 116 "json_parser.yy" { QVector* list = (yysemantic_stack_[(3) - (2)]).value* >(); (yyval) = QVariant(list->toList()); @@ -525,9 +525,9 @@ namespace yy { } break; - case 12: + case 11: /* Line 670 of lalr1.cc */ -#line 123 "json_parser.yy" +#line 122 "json_parser.yy" { QVector* list = new QVector(1); list->replace(0, (yysemantic_stack_[(1) - (1)])); @@ -535,9 +535,9 @@ namespace yy { } break; - case 13: + case 12: /* Line 670 of lalr1.cc */ -#line 128 "json_parser.yy" +#line 127 "json_parser.yy" { (yyval).value* >()->append((yysemantic_stack_[(3) - (3)])); } @@ -849,10 +849,10 @@ namespace yy { const signed char json_parser::yypact_[] = { - 1, -5, -5, 3, 18, -5, -5, -5, -5, -5, - 8, -5, -5, -5, -5, -5, 2, 11, -5, -3, - -5, -5, 29, -5, 4, -5, 29, -5, 13, -5, - 29, -5 + 0, -5, 2, 18, -5, -5, -5, -5, -5, 7, + -5, -5, -5, -5, -5, 1, 12, -5, -4, -5, + -5, 29, -5, 4, -5, 29, -5, 26, -5, 29, + -5 }; /* YYDEFACT[S] -- default reduction number in state S. Performed when @@ -861,24 +861,24 @@ namespace yy { const unsigned char json_parser::yydefact_[] = { - 0, 5, 4, 0, 0, 15, 16, 17, 18, 14, - 0, 2, 19, 20, 3, 6, 0, 0, 10, 0, - 12, 1, 0, 7, 0, 11, 0, 8, 0, 13, - 0, 9 + 0, 4, 0, 0, 14, 15, 16, 17, 13, 0, + 2, 18, 19, 3, 5, 0, 0, 9, 0, 11, + 1, 0, 6, 0, 10, 0, 7, 0, 12, 0, + 8 }; /* YYPGOTO[NTERM-NUM]. */ const signed char json_parser::yypgoto_[] = { - -5, -5, -5, -5, -5, -5, -5, -4 + -5, -5, -5, -5, -5, -5, -5, -3 }; /* YYDEFGOTO[NTERM-NUM]. */ const signed char json_parser::yydefgoto_[] = { - -1, 10, 11, 12, 17, 13, 19, 14 + -1, 9, 10, 11, 16, 12, 18, 13 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If @@ -888,21 +888,21 @@ namespace yy { const unsigned char json_parser::yytable_[] = { - 20, 1, 2, 25, 3, 26, 4, 15, 21, 22, - 5, 6, 7, 8, 9, 23, 16, 28, 27, 24, - 30, 3, 29, 4, 18, 0, 31, 5, 6, 7, - 8, 9, 3, 0, 4, 0, 0, 0, 5, 6, - 7, 8, 9 + 19, 1, 24, 2, 25, 3, 14, 20, 21, 4, + 5, 6, 7, 8, 0, 15, 22, 27, 26, 0, + 23, 2, 28, 3, 17, 0, 30, 4, 5, 6, + 7, 8, 2, 29, 3, 0, 0, 0, 4, 5, + 6, 7, 8 }; /* YYCHECK. */ const signed char json_parser::yycheck_[] = { - 4, 0, 1, 6, 3, 8, 5, 4, 0, 7, - 9, 10, 11, 12, 13, 4, 13, 13, 22, 8, - 7, 3, 26, 5, 6, -1, 30, 9, 10, 11, - 12, 13, 3, -1, 5, -1, -1, -1, 9, 10, + 3, 1, 6, 3, 8, 5, 4, 0, 7, 9, + 10, 11, 12, 13, -1, 13, 4, 13, 21, -1, + 8, 3, 25, 5, 6, -1, 29, 9, 10, 11, + 12, 13, 3, 7, 5, -1, -1, -1, 9, 10, 11, 12, 13 }; @@ -911,10 +911,10 @@ namespace yy { const unsigned char json_parser::yystos_[] = { - 0, 0, 1, 3, 5, 9, 10, 11, 12, 13, - 16, 17, 18, 20, 22, 4, 13, 19, 6, 21, - 22, 0, 7, 4, 8, 6, 8, 22, 13, 22, - 7, 22 + 0, 1, 3, 5, 9, 10, 11, 12, 13, 16, + 17, 18, 20, 22, 4, 13, 19, 6, 21, 22, + 0, 7, 4, 8, 6, 8, 22, 13, 22, 7, + 22 }; #if YYDEBUG @@ -932,18 +932,16 @@ namespace yy { const unsigned char json_parser::yyr1_[] = { - 0, 15, 16, 17, 17, 17, 18, 18, 19, 19, - 20, 20, 21, 21, 22, 22, 22, 22, 22, 22, - 22 + 0, 15, 16, 17, 17, 18, 18, 19, 19, 20, + 20, 21, 21, 22, 22, 22, 22, 22, 22, 22 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ const unsigned char json_parser::yyr2_[] = { - 0, 2, 1, 1, 1, 1, 2, 3, 3, 5, - 2, 3, 1, 3, 1, 1, 1, 1, 1, 1, - 1 + 0, 2, 1, 1, 1, 2, 3, 3, 5, 2, + 3, 1, 3, 1, 1, 1, 1, 1, 1, 1 }; @@ -963,12 +961,12 @@ namespace yy { const json_parser::rhs_number_type json_parser::yyrhs_[] = { - 16, 0, -1, 17, -1, 22, -1, 1, -1, 0, - -1, 3, 4, -1, 3, 19, 4, -1, 13, 7, - 22, -1, 19, 8, 13, 7, 22, -1, 5, 6, - -1, 5, 21, 6, -1, 22, -1, 21, 8, 22, - -1, 13, -1, 9, -1, 10, -1, 11, -1, 12, - -1, 18, -1, 20, -1 + 16, 0, -1, 17, -1, 22, -1, 1, -1, 3, + 4, -1, 3, 19, 4, -1, 13, 7, 22, -1, + 19, 8, 13, 7, 22, -1, 5, 6, -1, 5, + 21, 6, -1, 22, -1, 21, 8, 22, -1, 13, + -1, 9, -1, 10, -1, 11, -1, 12, -1, 18, + -1, 20, -1 }; /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in @@ -976,18 +974,16 @@ namespace yy { const unsigned char json_parser::yyprhs_[] = { - 0, 0, 3, 5, 7, 9, 11, 14, 18, 22, - 28, 31, 35, 37, 41, 43, 45, 47, 49, 51, - 53 + 0, 0, 3, 5, 7, 9, 12, 16, 20, 26, + 29, 33, 35, 39, 41, 43, 45, 47, 49, 51 }; /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ const unsigned char json_parser::yyrline_[] = { - 0, 82, 82, 87, 88, 94, 96, 99, 105, 110, - 114, 117, 123, 128, 132, 133, 134, 135, 136, 137, - 138 + 0, 82, 82, 87, 88, 95, 98, 104, 109, 113, + 116, 122, 127, 131, 132, 133, 134, 135, 136, 137 }; // Print the state stack on the debug stream. @@ -1064,7 +1060,7 @@ namespace yy { const int json_parser::yylast_ = 42; const int json_parser::yynnts_ = 8; const int json_parser::yyempty_ = -2; - const int json_parser::yyfinal_ = 21; + const int json_parser::yyfinal_ = 20; const int json_parser::yyterror_ = 1; const int json_parser::yyerrcode_ = 256; const int json_parser::yyntokens_ = 15; @@ -1075,9 +1071,9 @@ namespace yy { } // yy /* Line 1141 of lalr1.cc */ -#line 1079 "json_parser.cc" +#line 1075 "json_parser.cc" /* Line 1142 of lalr1.cc */ -#line 140 "json_parser.yy" +#line 139 "json_parser.yy" int yy::yylex(YYSTYPE *yylval, yy::location *yylloc, QJson::ParserPrivate* driver) diff --git a/src/webui/qjson/json_scanner.cc b/src/webui/qjson/json_scanner.cc index d148b0cd6..58f7d000b 100644 --- a/src/webui/qjson/json_scanner.cc +++ b/src/webui/qjson/json_scanner.cc @@ -3529,11 +3529,19 @@ YY_RULE_SETUP return yy::json_parser::token::STRING; } YY_BREAK +case YY_STATE_EOF(QUOTMARK_OPEN): +#line 173 "json_scanner.yy" +{ + qCritical() << "Unterminated string"; + m_yylloc->columns(yyleng); + return yy::json_parser::token::INVALID; + } + YY_BREAK case 24: YY_RULE_SETUP -#line 175 "json_scanner.yy" +#line 182 "json_scanner.yy" { QString hexDigits = QString::fromUtf8(yytext, yyleng); bool ok; @@ -3546,7 +3554,7 @@ YY_RULE_SETUP case 25: /* rule 25 can match eol */ YY_RULE_SETUP -#line 184 "json_scanner.yy" +#line 191 "json_scanner.yy" { qCritical() << "Invalid hex string"; m_yylloc->columns(yyleng); @@ -3559,7 +3567,7 @@ YY_RULE_SETUP /* "Compound type" related tokens */ case 26: YY_RULE_SETUP -#line 196 "json_scanner.yy" +#line 203 "json_scanner.yy" { m_yylloc->columns(yyleng); return yy::json_parser::token::COLON; @@ -3567,7 +3575,7 @@ YY_RULE_SETUP YY_BREAK case 27: YY_RULE_SETUP -#line 201 "json_scanner.yy" +#line 208 "json_scanner.yy" { m_yylloc->columns(yyleng); return yy::json_parser::token::COMMA; @@ -3575,7 +3583,7 @@ YY_RULE_SETUP YY_BREAK case 28: YY_RULE_SETUP -#line 206 "json_scanner.yy" +#line 213 "json_scanner.yy" { m_yylloc->columns(yyleng); return yy::json_parser::token::SQUARE_BRACKET_OPEN; @@ -3583,7 +3591,7 @@ YY_RULE_SETUP YY_BREAK case 29: YY_RULE_SETUP -#line 211 "json_scanner.yy" +#line 218 "json_scanner.yy" { m_yylloc->columns(yyleng); return yy::json_parser::token::SQUARE_BRACKET_CLOSE; @@ -3591,7 +3599,7 @@ YY_RULE_SETUP YY_BREAK case 30: YY_RULE_SETUP -#line 216 "json_scanner.yy" +#line 223 "json_scanner.yy" { m_yylloc->columns(yyleng); return yy::json_parser::token::CURLY_BRACKET_OPEN; @@ -3599,7 +3607,7 @@ YY_RULE_SETUP YY_BREAK case 31: YY_RULE_SETUP -#line 221 "json_scanner.yy" +#line 228 "json_scanner.yy" { m_yylloc->columns(yyleng); return yy::json_parser::token::CURLY_BRACKET_CLOSE; @@ -3609,7 +3617,7 @@ YY_RULE_SETUP case 32: YY_RULE_SETUP -#line 229 "json_scanner.yy" +#line 236 "json_scanner.yy" { m_yylloc->columns(yyleng); *m_yylval = QVariant(std::numeric_limits::quiet_NaN()); @@ -3618,7 +3626,7 @@ YY_RULE_SETUP YY_BREAK case 33: YY_RULE_SETUP -#line 235 "json_scanner.yy" +#line 242 "json_scanner.yy" { m_yylloc->columns(yyleng); *m_yylval = QVariant(std::numeric_limits::infinity()); @@ -3627,7 +3635,7 @@ YY_RULE_SETUP YY_BREAK case 34: YY_RULE_SETUP -#line 241 "json_scanner.yy" +#line 248 "json_scanner.yy" { m_yylloc->columns(yyleng); *m_yylval = QVariant(-std::numeric_limits::infinity()); @@ -3638,25 +3646,24 @@ YY_RULE_SETUP /* If all else fails */ case 35: YY_RULE_SETUP -#line 249 "json_scanner.yy" +#line 256 "json_scanner.yy" { m_yylloc->columns(yyleng); return yy::json_parser::token::INVALID; } YY_BREAK case YY_STATE_EOF(INITIAL): -case YY_STATE_EOF(QUOTMARK_OPEN): case YY_STATE_EOF(HEX_OPEN): case YY_STATE_EOF(ALLOW_SPECIAL_NUMBERS): -#line 254 "json_scanner.yy" +#line 261 "json_scanner.yy" return yy::json_parser::token::END; YY_BREAK case 36: YY_RULE_SETUP -#line 255 "json_scanner.yy" +#line 262 "json_scanner.yy" ECHO; YY_BREAK -#line 3660 "json_scanner.cc" +#line 3667 "json_scanner.cc" case YY_END_OF_BUFFER: { @@ -4510,4 +4517,4 @@ void yyfree (void * ptr ) #define YYTABLES_NAME "yytables" -#line 255 "json_scanner.yy" +#line 262 "json_scanner.yy" diff --git a/src/webui/qjson/parser.cpp b/src/webui/qjson/parser.cpp index 73de8ceae..723406697 100644 --- a/src/webui/qjson/parser.cpp +++ b/src/webui/qjson/parser.cpp @@ -1,6 +1,7 @@ /* This file is part of QJson * * Copyright (C) 2008 Flavio Castelli + * Copyright (C) 2016 Anton Kudryavtsev * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -31,9 +32,9 @@ using namespace QJson; ParserPrivate::ParserPrivate() : - m_scanner(0) + m_scanner(0), + m_specialNumbersAllowed(false) { - m_specialNumbersAllowed = false; reset(); } @@ -43,7 +44,7 @@ ParserPrivate::~ParserPrivate() delete m_scanner; } -void ParserPrivate::setError(QString errorMsg, int errorLine) { +void ParserPrivate::setError(const QString &errorMsg, int errorLine) { m_error = true; m_errorMsg = errorMsg; m_errorLine = errorLine; @@ -116,7 +117,7 @@ QVariant Parser::parse (QIODevice* io, bool* ok) QVariant Parser::parse(const QByteArray& jsonString, bool* ok) { QBuffer buffer; - buffer.open(QBuffer::ReadWrite); + buffer.open(QBuffer::ReadWrite | QBuffer::Text); buffer.write(jsonString); buffer.seek(0); return parse (&buffer, ok); diff --git a/src/webui/qjson/parser_p.h b/src/webui/qjson/parser_p.h index de98b9b6b..5589a3897 100644 --- a/src/webui/qjson/parser_p.h +++ b/src/webui/qjson/parser_p.h @@ -43,7 +43,7 @@ namespace QJson { void reset(); - void setError(QString errorMsg, int line); + void setError(const QString &errorMsg, int line); JSonScanner* m_scanner; bool m_error; diff --git a/src/webui/qjson/serializer.cpp b/src/webui/qjson/serializer.cpp index 25f9bb981..ede97bd93 100644 --- a/src/webui/qjson/serializer.cpp +++ b/src/webui/qjson/serializer.cpp @@ -2,6 +2,7 @@ * * Copyright (C) 2009 Till Adam * Copyright (C) 2009 Flavio Castelli + * Copyright (C) 2016 Anton Kudryavtsev * * 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 #include -#include +// 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 +#else +# include +#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& list, const QByteArray& sep ); + + static QByteArray buildIndent(int spaces); + static QByteArray escapeString( const QString& str ); + static QByteArray join( const QList& list, const QByteArray& sep ); + static QByteArray join( const QList& list, char sep ); }; QByteArray Serializer::SerializerPrivate::join( const QList& list, const QByteArray& sep ) { @@ -67,13 +76,24 @@ QByteArray Serializer::SerializerPrivate::join( const QList& list, c return res; } +QByteArray Serializer::SerializerPrivate::join( const QList& 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 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 it( vmap ); if (indentMode == QJson::IndentMinimum) { QByteArray indent = buildIndent(indentLevel); @@ -135,18 +154,17 @@ QByteArray Serializer::SerializerPrivate::serialize( const QVariant &v, bool *ok } QList 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 it( vhash ); if (indentMode == QJson::IndentMinimum) { QByteArray indent = buildIndent(indentLevel); @@ -195,18 +212,16 @@ QByteArray Serializer::SerializerPrivate::serialize( const QVariant &v, bool *ok } QList 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() ); - } else if ( v.type() == QVariant::UInt ) { // unsigned int number? + } else if ( type == QVariant::UInt ) { // unsigned int number? str += QByteArray::number( v.value() ); } else if ( v.canConvert() ) { // any signed number? str += QByteArray::number( v.value() ); @@ -297,7 +312,7 @@ QByteArray Serializer::SerializerPrivate::serialize( const QVariant &v, bool *ok str += QByteArray::number( v.value() ); } else if ( v.canConvert() ){ // 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(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()