summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Schmertmann <Lars.Schmertmann@governikus.de>2016-12-18 21:15:10 +0100
committerLars Schmertmann <lars.schmertmann@governikus.de>2016-12-25 08:24:18 +0000
commit5882866768ae24ef31f9feda4765fea17375fbcb (patch)
tree4cf9c7b57e25d7969aac27c45126d8bde7908714
parent615027129d3d5e12a6e2f5d02d2af8320cc58ea7 (diff)
Extend qChecksum calculation
ISO 14443-3 is for nfc communication and uses 2 different checksums. The existing one is from ISO 3309 and the other one is from ITU-V.41. Both are needed to implement an own transport layer defined in ISO 14443-4 to allow nfc commands with a length above 250 byte independent from the smartphone. This change will avoid code duplication in QNearFieldTarget. The private function qNfcChecksum is a copy of qChecksum. Change-Id: I790ffec8e2ea46f88b2db6f48b64fdcb140e7b70 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r--src/corelib/global/qnamespace.h6
-rw-r--r--src/corelib/global/qnamespace.qdoc11
-rw-r--r--src/corelib/tools/qbytearray.cpp40
-rw-r--r--src/corelib/tools/qbytearray.h4
-rw-r--r--tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp30
5 files changed, 85 insertions, 6 deletions
diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h
index 873a36f4a6..c3833c6bd1 100644
--- a/src/corelib/global/qnamespace.h
+++ b/src/corelib/global/qnamespace.h
@@ -1656,6 +1656,11 @@ public:
};
Q_DECLARE_FLAGS(MouseEventFlags, MouseEventFlag)
+ enum ChecksumType {
+ ChecksumIso3309,
+ ChecksumItuV41
+ };
+
#ifndef Q_QDOC
// NOTE: Generally, do not add QT_Q_ENUM if a corresponding Q_Q_FLAG exists.
QT_Q_ENUM(ScrollBarPolicy)
@@ -1740,6 +1745,7 @@ public:
QT_Q_ENUM(ScrollPhase)
QT_Q_ENUM(MouseEventSource)
QT_Q_FLAG(MouseEventFlag)
+ QT_Q_ENUM(ChecksumType)
QT_Q_ENUM(TabFocusBehavior)
#endif // Q_DOC
diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc
index 64f0b5e1da..dfecc3e2d3 100644
--- a/src/corelib/global/qnamespace.qdoc
+++ b/src/corelib/global/qnamespace.qdoc
@@ -3158,3 +3158,14 @@
\omitvalue MouseEventFlagMask
*/
+
+/*!
+ \enum Qt::ChecksumType
+ \since 5.9
+
+ This enum describes the possible standards used by qChecksum().
+
+ \value ChecksumIso3309 Checksum calculation based on ISO 3309.
+
+ \value ChecksumItuV41 Checksum calculation based on ITU-V.41.
+*/
diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp
index 82c88ca694..329cc358d4 100644
--- a/src/corelib/tools/qbytearray.cpp
+++ b/src/corelib/tools/qbytearray.cpp
@@ -541,15 +541,40 @@ static const quint16 crc_tbl[16] = {
Returns the CRC-16 checksum of the first \a len bytes of \a data.
- The checksum is independent of the byte order (endianness).
+ The checksum is independent of the byte order (endianness) and will be
+ calculated accorded to the algorithm published in ISO 3309 (Qt::ChecksumIso3309).
\note This function is a 16-bit cache conserving (16 entry table)
implementation of the CRC-16-CCITT algorithm.
*/
-
quint16 qChecksum(const char *data, uint len)
{
- quint16 crc = 0xffff;
+ return qChecksum(data, len, Qt::ChecksumIso3309);
+}
+
+/*!
+ \relates QByteArray
+ \since 5.9
+
+ Returns the CRC-16 checksum of the first \a len bytes of \a data.
+
+ The checksum is independent of the byte order (endianness) and will
+ be calculated accorded to the algorithm published in \a standard.
+
+ \note This function is a 16-bit cache conserving (16 entry table)
+ implementation of the CRC-16-CCITT algorithm.
+*/
+quint16 qChecksum(const char *data, uint len, Qt::ChecksumType standard)
+{
+ quint16 crc = 0x0000;
+ switch (standard) {
+ case Qt::ChecksumIso3309:
+ crc = 0xffff;
+ break;
+ case Qt::ChecksumItuV41:
+ crc = 0x6363;
+ break;
+ }
uchar c;
const uchar *p = reinterpret_cast<const uchar *>(data);
while (len--) {
@@ -558,7 +583,14 @@ quint16 qChecksum(const char *data, uint len)
c >>= 4;
crc = ((crc >> 4) & 0x0fff) ^ crc_tbl[((crc ^ c) & 15)];
}
- return ~crc & 0xffff;
+ switch (standard) {
+ case Qt::ChecksumIso3309:
+ crc = ~crc;
+ break;
+ case Qt::ChecksumItuV41:
+ break;
+ }
+ return crc & 0xffff;
}
/*!
diff --git a/src/corelib/tools/qbytearray.h b/src/corelib/tools/qbytearray.h
index cb94b30c2d..af85d27868 100644
--- a/src/corelib/tools/qbytearray.h
+++ b/src/corelib/tools/qbytearray.h
@@ -105,8 +105,8 @@ Q_CORE_EXPORT int qvsnprintf(char *str, size_t n, const char *fmt, va_list ap);
Q_CORE_EXPORT int qsnprintf(char *str, size_t n, const char *fmt, ...);
// qChecksum: Internet checksum
-
-Q_CORE_EXPORT quint16 qChecksum(const char *s, uint len);
+Q_CORE_EXPORT quint16 qChecksum(const char *s, uint len); // ### Qt 6: Remove
+Q_CORE_EXPORT quint16 qChecksum(const char *s, uint len, Qt::ChecksumType standard); // ### Qt 6: Use Qt::ChecksumType standard = Qt::ChecksumIso3309
class QByteRef;
class QString;
diff --git a/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp b/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp
index 324086dbab..16a9c03351 100644
--- a/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp
+++ b/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp
@@ -43,6 +43,8 @@ public:
tst_QByteArray();
private slots:
void swap();
+ void qChecksum_data();
+ void qChecksum();
void qCompress_data();
#ifndef QT_NO_COMPRESS
void qCompress();
@@ -239,6 +241,34 @@ tst_QByteArray::tst_QByteArray()
{
}
+void tst_QByteArray::qChecksum_data()
+{
+ QTest::addColumn<QByteArray>("data");
+ QTest::addColumn<uint>("len");
+ QTest::addColumn<Qt::ChecksumType>("standard");
+ QTest::addColumn<uint>("checksum");
+
+ // Examples from ISO 14443-3
+ QTest::newRow("1") << QByteArray("\x00\x00") << 2U << Qt::ChecksumItuV41 << 0x1EA0U;
+ QTest::newRow("2") << QByteArray("\x12\x34") << 2U << Qt::ChecksumItuV41 << 0xCF26U;
+ QTest::newRow("3") << QByteArray("\x00\x00\x00") << 3U << Qt::ChecksumIso3309 << 0xC6CCU;
+ QTest::newRow("4") << QByteArray("\x0F\xAA\xFF") << 3U << Qt::ChecksumIso3309 << 0xD1FCU;
+ QTest::newRow("5") << QByteArray("\x0A\x12\x34\x56") << 4U << Qt::ChecksumIso3309 << 0xF62CU;
+}
+
+void tst_QByteArray::qChecksum()
+{
+ QFETCH(QByteArray, data);
+ QFETCH(uint, len);
+ QFETCH(Qt::ChecksumType, standard);
+ QFETCH(uint, checksum);
+
+ if (standard == Qt::ChecksumIso3309) {
+ QCOMPARE(::qChecksum(data.constData(), len), static_cast<quint16>(checksum));
+ }
+ QCOMPARE(::qChecksum(data.constData(), len, standard), static_cast<quint16>(checksum));
+}
+
void tst_QByteArray::qCompress_data()
{
QTest::addColumn<QByteArray>("ba");