Location>code7788 >text

Implementing Asynchronous Hashers in Qt

Popularity:972 ℃/2024-09-11 10:32:52

[Writing in front]

In many jobs, we need to calculate the hash value of data or files, such as logging in or downloading files.

In Qt, the classes responsible for this areQCryptographicHash

with respect toQCryptographicHash

QCryptographicHash is a class provided in the Qt framework for generating cryptographic hashes (hashes). The class converts inputs of arbitrary length (binary or text data) into outputs of fixed length (hashes), a process that is irreversible.QCryptographicHash Multiple hash algorithms are supported, includingMD4, MD5, SHA-1, SHA-224, SHA-256, SHA-384 sum SHA-512 etc., these algorithms are very useful in application scenarios such as data integrity verification, cryptographic storage, and digital signatures.

Key Features:

  1. Multiple hash algorithms are supported:QCryptographicHash Provides support for a variety of hash algorithms, allowing developers to choose the appropriate algorithm for their specific needs.
  2. Easy-to-use interface:QCryptographicHash Provides easy-to-use interface to calculate hashes. Developers can calculate the hash value by calling theQCryptographicHash::hash() Static methods or createQCryptographicHash object and use theaddData() cap (a poem)result() method to compute the hash.
  3. Chunk-by-chunk: `QCryptographicHash also calculates hashes chunk-by-chunk, which is useful for working with large files or streaming data.
  4. Reusable:QCryptographicHash Objects can be used multiple times. When a hash has been calculated, it can be used multiple times by calling thereset() method resets the object and then proceeds to compute a new hash value.

But then, althoughQCryptographicHash It's excellent, but its biggest problem is that its hash calculation is synchronized (i.e., blocking), which doesn't matter much for small data, but implies noticeable lag for big data.

Therefore, I willQCryptographicHash Simple encapsulation to extend the utility and change the computation to asynchronous, and add progress notification and end notification.


[Text Begins]

Let's take a look.AsyncHasher The use of the effect diagram:

image

AsyncHasher It is very simple to use:

  1. Include header files: When using theAsyncHasher Before that, you need to include the appropriate header files#include ""

  2. pass (a bill or inspection etc)setSource / setSourceText / setSourceData/ setSourceObject Set the source target.

  3. pass (a bill or inspection etc)void hashProgress(qint64 processed, qint64 total) to get the progress.void finished() Notification of the end of the calculation.

  4. pass (a bill or inspection etc)QString hashValue() const Get the final results.

Used by C++, for example:

    AsyncHasher *hasher = new AsyncHasher;
    hasher->setSourceText("Test Text");
    QObject::connect(hasher, &AsyncHasher::finished, [hasher]{
        qDebug() << hasher->hashValue();
    });

And I've also made Qml adaptations to use it:

    AsyncHasher {
        id: textHasher
        algorithm: AsyncHasher.Md5
        onStarted: {
            startTime = ();
        }
        onFinished: {
            totalTime = () - startTime;
            ("HashValue:", hashValue, "time:", totalTime);
        }
        property real startTime: 0
        property real totalTime: 0
    }

The full header file is below:

#ifndef ASYNCHASHER_H
#define ASYNCHASHER_H

#include <QCryptographicHash>
#include <QFuture>
#include <QObject>
#include <QUrl>

QT_FORWARD_DECLARE_CLASS(QNetworkAccessManager);

QT_FORWARD_DECLARE_CLASS(AsyncHasherPrivate);

class AsyncHasher : public QObject
{
    Q_OBJECT

    Q_PROPERTY(QCryptographicHash::Algorithm algorithm READ algorithm WRITE setAlgorithm NOTIFY algorithmChanged)
    Q_PROPERTY(bool asynchronous READ asynchronous WRITE setAsynchronous NOTIFY asynchronousChanged)
    Q_PROPERTY(QString hashValue READ hashValue NOTIFY hashValueChanged)
    Q_PROPERTY(int hashLength READ hashLength NOTIFY hashLengthChanged)
    Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
    Q_PROPERTY(QString sourceText READ sourceText WRITE setSourceText NOTIFY sourceTextChanged)
    Q_PROPERTY(QByteArray sourceData READ sourceData WRITE setSourceData NOTIFY sourceDataChanged)
    Q_PROPERTY(QObject* sourceObject READ sourceObject WRITE setSourceObject NOTIFY sourceObjectChanged)

public:
    Q_ENUMS(QCryptographicHash::Algorithm);

    explicit AsyncHasher(QObject *parent = nullptr);
    ~AsyncHasher();

    QNetworkAccessManager *networkManager() const;

    QCryptographicHash::Algorithm algorithm();
    void setAlgorithm(QCryptographicHash::Algorithm algorithm);

    bool asynchronous() const;
    void setAsynchronous(bool async);

    QString hashValue() const;

    int hashLength() const;

    QUrl source() const;
    void setSource(const QUrl &source);

    QString sourceText() const;
    void setSourceText(const QString &sourceText);

    QByteArray sourceData() const;
    void setSourceData(const QByteArray &sourceData);

    QObject *sourceObject() const;
    void setSourceObject(QObject *sourceObject);

    bool operator==(const AsyncHasher &hasher);
    bool operator!=(const AsyncHasher &hasher);

    QFuture<QByteArray> static hash(const QByteArray &data, QCryptographicHash::Algorithm algorithm);

signals:
    void algorithmChanged();
    void asynchronousChanged();
    void hashValueChanged();
    void hashLengthChanged();
    void sourceChanged();
    void sourceTextChanged();
    void sourceDataChanged();
    void sourceObjectChanged();
    void hashProgress(qint64 processed, qint64 total);
    void started();
    void finished();

private slots:
    void setHashValue(const QString &value);

private:
    Q_DECLARE_PRIVATE(AsyncHasher);
    QScopedPointer<AsyncHasherPrivate> d_ptr;
};

#endif // ASYNCHASHER_H

[Conclusion]

And finally: project link (more star yah...). ⭐_⭐):

Github Address:/mengps/QmlControls/tree/master/AsyncHasher