diff options
author | Lars Schmertmann <Lars.Schmertmann@governikus.de> | 2016-12-18 21:15:10 +0100 |
---|---|---|
committer | Lars Schmertmann <lars.schmertmann@governikus.de> | 2016-12-25 08:24:18 +0000 |
commit | 5882866768ae24ef31f9feda4765fea17375fbcb (patch) | |
tree | 4cf9c7b57e25d7969aac27c45126d8bde7908714 | |
parent | 615027129d3d5e12a6e2f5d02d2af8320cc58ea7 (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.h | 6 | ||||
-rw-r--r-- | src/corelib/global/qnamespace.qdoc | 11 | ||||
-rw-r--r-- | src/corelib/tools/qbytearray.cpp | 40 | ||||
-rw-r--r-- | src/corelib/tools/qbytearray.h | 4 | ||||
-rw-r--r-- | tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp | 30 |
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"); |