Add 'well-formated' JSON string values

Add support for surrogate code points U+D800 through U+DFFF,
represent them with JSON escape sequences.

https://github.com/tc39/proposal-well-formed-stringify

Change-Id: I84fea53a8ef400beebefdba10ea82dc510fe7dda
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Michal Klocek 2019-05-02 18:02:45 +02:00
parent fa59c4fd7d
commit 1e5deb0641
2 changed files with 34 additions and 5 deletions

View File

@ -58,7 +58,6 @@ static inline uchar hexdig(uint u)
static QByteArray escapedString(const QString &s)
{
const uchar replacement = '?';
QByteArray ba(s.length(), Qt::Uninitialized);
uchar *cursor = reinterpret_cast<uchar *>(const_cast<char *>(ba.constData()));
@ -111,9 +110,14 @@ static QByteArray escapedString(const QString &s)
} else {
*cursor++ = (uchar)u;
}
} else {
if (QUtf8Functions::toUtf8<QUtf8BaseTraits>(u, cursor, src, end) < 0)
*cursor++ = replacement;
} else if (QUtf8Functions::toUtf8<QUtf8BaseTraits>(u, cursor, src, end) < 0) {
// failed to get valid utf8 use JSON escape sequence
*cursor++ = '\\';
*cursor++ = 'u';
*cursor++ = hexdig(u>>12 & 0x0f);
*cursor++ = hexdig(u>>8 & 0x0f);
*cursor++ = hexdig(u>>4 & 0x0f);
*cursor++ = hexdig(u & 0x0f);
}
}

View File

@ -163,7 +163,8 @@ private Q_SLOTS:
void streamSerializationQJsonValue();
void streamSerializationQJsonValueEmpty();
void streamVariantSerialization();
void escapeSurrogateCodePoints_data();
void escapeSurrogateCodePoints();
private:
QString testDataDir;
};
@ -3093,6 +3094,9 @@ void tst_QtJson::streamSerializationQJsonValue_data()
QTest::newRow("string") << QJsonValue{QStringLiteral("bum")};
QTest::newRow("array") << QJsonValue{QJsonArray{12,1,5,6,7}};
QTest::newRow("object") << QJsonValue{QJsonObject{{"foo", 665}, {"bar", 666}}};
// test json escape sequence
QTest::newRow("array with 0xD800") << QJsonValue(QJsonArray{QString(0xD800)});
QTest::newRow("array with 0xDF06,0xD834") << QJsonValue(QJsonArray{QString(0xDF06).append(0xD834)});
}
void tst_QtJson::streamSerializationQJsonValue()
@ -3181,5 +3185,26 @@ void tst_QtJson::streamVariantSerialization()
}
}
void tst_QtJson::escapeSurrogateCodePoints_data()
{
QTest::addColumn<QString>("str");
QTest::addColumn<QByteArray>("escStr");
QTest::newRow("0xD800") << QString(0xD800) << QByteArray("\\ud800");
QTest::newRow("0xDF06,0xD834") << QString(0xDF06).append(0xD834) << QByteArray("\\udf06\\ud834");
}
void tst_QtJson::escapeSurrogateCodePoints()
{
QFETCH(QString, str);
QFETCH(QByteArray, escStr);
QJsonArray array;
array.append(str);
QByteArray buffer;
QDataStream save(&buffer, QIODevice::WriteOnly);
save << array;
// verify the buffer has escaped values
QVERIFY(buffer.contains(escStr));
}
QTEST_MAIN(tst_QtJson)
#include "tst_qtjson.moc"