Skip to content

Commit

Permalink
Clean up.
Browse files Browse the repository at this point in the history
  • Loading branch information
Ummon committed Aug 31, 2014
1 parent 3406731 commit d31aa85
Show file tree
Hide file tree
Showing 5 changed files with 220 additions and 199 deletions.
8 changes: 5 additions & 3 deletions application/Common/Common.pro
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ CONFIG += staticlib \
INCLUDEPATH += . ..
DEFINES += COMMON_LIBRARY

SOURCES += Hash.cpp \
SOURCES += \
Global.cpp \
ZeroCopyStreamQIODevice.cpp \
Settings.cpp \
Expand All @@ -39,7 +39,8 @@ SOURCES += Hash.cpp \
StringUtils.cpp \
Network/Message.cpp \
KnownExtensions.cpp \
Hash_noShare.cpp
Hash_noShare.cpp \
Hash_share.cpp

HEADERS += Hashes.h \
Hash.h \
Expand Down Expand Up @@ -74,6 +75,7 @@ HEADERS += Hashes.h \
Containers/SortedArray.h \
Containers/MapArray.h \
SelfWeakPointer.h \
Hash_noShare.h
Hash_noShare.h \
Hash_share.h


195 changes: 4 additions & 191 deletions application/Common/Hash.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,199 +19,12 @@
#ifndef COMMON_HASH_H
#define COMMON_HASH_H

#define NO_SHARED_DATA true
#define SHARED_DATA false

#if NO_SHARED_DATA
# include <Common/Hash_noShare.h>
#if SHARED_DATA
# include <Common/Hash_share.h>
#else

#define WITH_MUTEX false // Not implemented. Using a 'QAtomicPointer' instead of a mutex should be better.

#include <string>

#include <QString>
#include <QByteArray>
#include <QDataStream>
#include <QCryptographicHash>

#include <Libs/MersenneTwister.h>

#if WITH_MUTEX
# include <QMutex>
# include <Common/Hash_noShare.h>
#endif

#include <Common/Uncopyable.h>

namespace Common
{
class Hasher;
class Hash
{
static MTRand mtrand;

public:
static const int HASH_SIZE = 20;

private:
static const char NULL_HASH[HASH_SIZE];

public:
Hash() noexcept;
Hash(const Hash& h) noexcept;
Hash(Hash&& h) noexcept;

explicit Hash(const char* h); // It's too dangerous to construct an implicit Hash from a const char*.
Hash(const std::string& str);
Hash(const QByteArray& a);

~Hash();

Hash& operator=(const Hash& h);
Hash& operator=(Hash&& h) noexcept;

/**
* Return a pointer to its internal data.
* The length of the returned value is exactly HASH_SIZE.
*/
inline const char* getData() const noexcept { return this->data ? this->data->hash : NULL_HASH; }
inline QByteArray getByteArray() const { return QByteArray(this->data ? this->data->hash : NULL_HASH, HASH_SIZE); }

QString toStr() const;
QString toStrCArray() const;
bool isNull() const noexcept;

static Hash rand();
static Hash rand(quint32 seed);
static void setRandSeed(quint32 seed);
static Hash fromStr(const QString& str);

private:
inline void dereference();
inline void newData();

friend QDataStream& operator>>(QDataStream&, Hash&);
friend QDataStream& operator<<(QDataStream& stream, const Hash& hash);
friend bool operator==(const Hash& h1, const Hash& h2);
friend class Hasher;

struct SharedData
{
int nbRef;
char hash[HASH_SIZE];
};

SharedData* data;
};

/**
* It will read an hash from a data stream and modify the given hash.
*/
inline QDataStream& operator>>(QDataStream& stream, Hash& hash)
{
char data[Hash::HASH_SIZE];
if (stream.readRawData(data, Hash::HASH_SIZE) != Hash::HASH_SIZE)
return stream;

if (memcmp(Hash::NULL_HASH, data, Hash::HASH_SIZE) == 0)
{
if (hash.data)
{
hash.dereference();
hash.data = 0;
}
}
else if (!hash.data || memcmp(hash.data->hash, data, Hash::HASH_SIZE) != 0)
{
hash.dereference();
hash.newData();
memcpy(hash.data->hash, data, Hash::HASH_SIZE);
}

return stream;
}

/**
* It will write an hash to a data stream.
*/
inline QDataStream& operator<<(QDataStream& stream, const Hash& hash)
{
if (hash.data)
stream.writeRawData(hash.data->hash, Hash::HASH_SIZE);
else
stream.writeRawData(Hash::NULL_HASH, Hash::HASH_SIZE);

return stream;
}

inline bool operator==(const Hash& h1, const Hash& h2)
{
return h1.data == h2.data || memcmp(h1.getData(), h2.getData(), Hash::HASH_SIZE) == 0;
}

inline bool operator!=(const Hash& h1, const Hash& h2)
{
return !(h1 == h2);
}

inline bool operator<(const Hash& h1, const Hash& h2)
{
return memcmp(h1.getData(), h2.getData(), Hash::HASH_SIZE) < 0;
}

/**
* Used by QHash.
*/
inline uint qHash(const Hash& h)
{
// Take the first sizeof(uint) bytes of the hash data.
if (h.isNull())
return 0;
else
return *(const uint*)(h.getData());
}

class Hasher : Uncopyable
{
static MTRand mtrand;

public:
Hasher();
// void addPredefinedSalt(); Deprecated.
void addSalt(quint64 salt);
void addData(const char*, int size);
Hash getResult();
void reset();

static Common::Hash hash(const QString& str);
static Common::Hash hash(const Common::Hash& hash);
static Common::Hash hashWithSalt(const QString& str, quint64 salt);
static Common::Hash hashWithSalt(const Common::Hash& hash, quint64 salt);
static Common::Hash hashWithRandomSalt(const QString& str, quint64& salt);
static Common::Hash hashWithRandomSalt(const Common::Hash& hash, quint64& salt);

private:
QCryptographicHash cryptographicHash;
};
}

/**
* Removes the reference to the pointed data if it exists.
*/
inline void Common::Hash::dereference()
{
if (this->data)
{
this->data->nbRef -= 1;
if (this->data->nbRef == 0)
delete this->data;
}
}

inline void Common::Hash::newData()
{
this->data = new SharedData;
this->data->nbRef = 1;
}

#endif
#endif
4 changes: 2 additions & 2 deletions application/Common/Hash_noShare.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

#include <Common/Hash.h>

#if NO_SHARED_DATA
#if !SHARED_DATA

#include <Common/Hash_noShare.h>
using namespace Common;
Expand Down Expand Up @@ -80,7 +80,7 @@ Hash::Hash(const QByteArray& a)

/**
* Return a human readable string.
* For example : 16bd4b1e656129eb9ddaa2ce0f0705f1cc161f77.
* For example : "16bd4b1e656129eb9ddaa2ce0f0705f1cc161f77".
* @see fromStr to decode a such string.
*/
QString Hash::toStr() const
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@
*/

#include <Common/Hash.h>
using namespace Common;

#if !NO_SHARED_DATA
#if SHARED_DATA

#include <Common/Hash_share.h>
using namespace Common;

#include <QtGlobal>
#include <QTime>
Expand Down Expand Up @@ -105,7 +107,7 @@ Hash::Hash(const std::string& str)
* The data are copied, no pointer is keept to 'a'.
*/
Hash::Hash(const QByteArray& a)
{
{
Q_ASSERT_X(a.size() == HASH_SIZE, "Hash::Hash", QString("The given QByteArray must have a size of %1").arg(HASH_SIZE).toUtf8().constData());

if (a.isNull() || a.size() != HASH_SIZE || memcmp(a.constData(), NULL_HASH, Hash::HASH_SIZE) == 0)
Expand Down
Loading

0 comments on commit d31aa85

Please sign in to comment.