Core: Reworked hashes

-Removed HashDigest class (replaced by ByteArray)
-Removed Hashable/Hash classes (replaced by ComputeHash function and
Hashable template struct)
-Fixed ByteArray operator<<
-Renamed File::GetHash to File::ComputeHash


Former-commit-id: cc5eaf2d4c88a556878190b8205e66713512e2d2
This commit is contained in:
Lynix
2015-11-16 14:04:39 +01:00
parent 86da939520
commit 21f223f1c7
37 changed files with 294 additions and 621 deletions

View File

@@ -8,10 +8,12 @@
#define NAZARA_ABSTRACTHASH_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Enums.hpp>
#include <memory>
namespace Nz
{
class HashDigest;
class ByteArray;
class NAZARA_CORE_API AbstractHash
{
@@ -23,10 +25,15 @@ namespace Nz
virtual void Append(const UInt8* data, unsigned int len) = 0;
virtual void Begin() = 0;
virtual HashDigest End() = 0;
virtual ByteArray End() = 0;
virtual unsigned int GetDigestLength() const = 0;
virtual const char* GetHashName() const = 0;
AbstractHash& operator=(const AbstractHash&) = delete;
AbstractHash& operator=(AbstractHash&&) = default;
static std::unique_ptr<AbstractHash> Get(HashType hash);
};
}

View File

@@ -8,15 +8,24 @@
#define NAZARA_ALGORITHM_CORE_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Enums.hpp>
#include <functional>
#include <tuple>
namespace Nz
{
class AbstractHash;
class ByteArray;
template<typename F, typename Tuple> auto Apply(F&& fn, Tuple&& t);
template<typename O, typename F, typename Tuple> auto Apply(O& object, F&& fn, Tuple&& t);
template<typename T> ByteArray ComputeHash(HashType hash, const T& v);
template<typename T> ByteArray ComputeHash(AbstractHash* hash, const T& v);
template<typename T> void HashCombine(std::size_t& seed, const T& v);
template<typename T>
struct Hashable;
template<typename T>
struct TypeTag {};
}

View File

@@ -6,6 +6,7 @@
// Merci à Ryan "FullMetal Alchemist" Lahfa
// Merci aussi à Freedom de siteduzero.com
#include <Nazara/Core/AbstractHash.hpp>
#include <Nazara/Core/Debug.hpp>
namespace Nz
@@ -41,6 +42,21 @@ namespace Nz
return Detail::ApplyImplMethod(object, std::forward<F>(fn), std::forward<Tuple>(t), std::make_index_sequence<tSize>());
}
template<typename T>
ByteArray ComputeHash(HashType hash, const T& v)
{
return ComputeHash(AbstractHash::Get(hash).get(), v);
}
template<typename T>
ByteArray ComputeHash(AbstractHash* hash, const T& v)
{
hash->Begin();
Hashable<T>()(v, hash);
return hash->End();
}
// Algorithme venant de CityHash par Google
// http://stackoverflow.com/questions/8513911/how-to-create-a-good-hash-combine-with-64-bit-output-inspired-by-boosthash-co
template<typename T>

View File

@@ -8,8 +8,6 @@
#define NAZARA_BYTEARRAY_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/Hashable.hpp>
#include <Nazara/Core/String.hpp>
#include <vector>
@@ -17,7 +15,7 @@ namespace Nz
{
class AbstractHash;
class NAZARA_CORE_API ByteArray : public Hashable
class NAZARA_CORE_API ByteArray
{
using Container = std::vector<UInt8>;
@@ -90,6 +88,7 @@ namespace Nz
inline void ShrinkToFit();
inline void Swap(ByteArray& other);
inline String ToHex() const;
inline String ToString() const;
// STL interface
@@ -109,6 +108,8 @@ namespace Nz
inline size_type size() const noexcept;
// Operators
NAZARA_CORE_API friend std::ostream& operator<<(std::ostream& out, const Nz::ByteArray& byteArray);
inline reference operator[](size_type pos);
inline const_reference operator[](size_type pos) const;
inline ByteArray& operator=(const ByteArray& array) = default;
@@ -124,13 +125,12 @@ namespace Nz
inline bool operator>=(const ByteArray& rhs) const;
private:
bool FillHash(AbstractHash* hash) const;
Container m_array;
};
}
NAZARA_CORE_API std::ostream& operator<<(std::ostream& out, const Nz::ByteArray& byteArray);
template<>
struct Hashable<ByteArray>;
}
namespace std
{

View File

@@ -193,6 +193,17 @@ namespace Nz
m_array.swap(other.m_array);
}
inline String ByteArray::ToHex() const
{
unsigned int length = m_array.size() * 2;
String hexOutput(length, '\0');
for (unsigned int i = 0; i < m_array.size(); ++i)
std::sprintf(&hexOutput[i * 2], "%02x", m_array[i]);
return hexOutput;
}
inline String ByteArray::ToString() const
{
return String(reinterpret_cast<const char*>(GetConstBuffer()), GetSize());
@@ -321,6 +332,16 @@ namespace Nz
{
return m_array >= rhs.m_array;
}
template<>
struct Hashable<ByteArray>
{
bool operator()(const ByteArray& byteArray, AbstractHash* hash) const
{
hash->Append(byteArray.GetConstBuffer(), byteArray.GetSize());
return true;
}
};
}
namespace std

View File

@@ -11,8 +11,6 @@
#include <Nazara/Core/ByteArray.hpp>
#include <Nazara/Core/Directory.hpp>
#include <Nazara/Core/Endianness.hpp>
#include <Nazara/Core/Hashable.hpp>
#include <Nazara/Core/HashDigest.hpp>
#include <Nazara/Core/InputStream.hpp>
#include <Nazara/Core/String.hpp>
@@ -28,7 +26,7 @@ namespace Nz
{
class FileImpl;
class NAZARA_CORE_API File : public Hashable, public InputStream
class NAZARA_CORE_API File : public InputStream
{
public:
File();
@@ -83,6 +81,8 @@ namespace Nz
File& operator=(File&& file) noexcept;
static String AbsolutePath(const String& filePath);
static inline ByteArray ComputeHash(HashType hash, const String& filePath);
static inline ByteArray ComputeHash(AbstractHash* hash, const String& filePath);
static bool Copy(const String& sourcePath, const String& targetPath);
static bool Delete(const String& filePath);
static bool Exists(const String& filePath);
@@ -90,8 +90,6 @@ namespace Nz
static String GetDirectory(const String& filePath);
static time_t GetLastAccessTime(const String& filePath);
static time_t GetLastWriteTime(const String& filePath);
static HashDigest GetHash(const String& filePath, HashType hash);
static HashDigest GetHash(const String& filePath, AbstractHash* hash);
static UInt64 GetSize(const String& filePath);
static bool IsAbsolute(const String& filePath);
static String NormalizePath(const String& filePath);
@@ -99,8 +97,6 @@ namespace Nz
static bool Rename(const String& sourcePath, const String& targetPath);
private:
bool FillHash(AbstractHash* hash) const;
NazaraMutexAttrib(m_mutex, mutable)
Endianness m_endianness;
@@ -108,6 +104,11 @@ namespace Nz
FileImpl* m_impl;
unsigned int m_openMode;
};
template<>
struct Hashable<File>;
}
#include <Nazara/Core/File.inl>
#endif // NAZARA_FILE_HPP

View File

@@ -0,0 +1,56 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/AbstractHash.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/ByteArray.hpp>
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
inline ByteArray File::ComputeHash(HashType hash, const String& filePath)
{
return ComputeHash(AbstractHash::Get(hash).get(), filePath);
}
inline ByteArray File::ComputeHash(AbstractHash* hash, const String& filePath)
{
return Nz::ComputeHash(hash, File(filePath));
}
template<>
struct Hashable<File>
{
bool operator()(const Nz::File& originalFile, AbstractHash* hash) const
{
File file(originalFile.GetPath());
if (!file.Open(OpenMode_ReadOnly))
{
NazaraError("Unable to open file");
return false;
}
UInt64 remainingSize = file.GetSize();
char buffer[NAZARA_CORE_FILE_BUFFERSIZE];
while (remainingSize > 0)
{
unsigned int size = static_cast<unsigned int>(std::min(remainingSize, static_cast<UInt64>(NAZARA_CORE_FILE_BUFFERSIZE)));
if (file.Read(&buffer[0], sizeof(char), size) != sizeof(char)*size)
{
NazaraError("Unable to read file");
return false;
}
remainingSize -= size;
hash->Append(reinterpret_cast<UInt8*>(&buffer[0]), size);
}
return true;
}
};
}
#include <Nazara/Core/DebugOff.hpp>

View File

@@ -1,36 +0,0 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_HASH_HPP
#define NAZARA_HASH_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/AbstractHash.hpp>
#include <Nazara/Core/Hashable.hpp>
#include <Nazara/Core/HashDigest.hpp>
namespace Nz
{
class NAZARA_CORE_API Hash
{
public:
Hash(HashType hash);
Hash(AbstractHash* hashImpl);
Hash(const Hash&) = delete;
Hash(Hash&&) = delete; ///TODO
~Hash();
HashDigest Process(const Hashable& hashable);
Hash& operator=(const Hash&) = delete;
Hash& operator=(Hash&&) = delete; ///TODO
private:
AbstractHash* m_impl;
};
}
#endif // NAZARA_HASH_HPP

View File

@@ -9,7 +9,7 @@
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/AbstractHash.hpp>
#include <Nazara/Core/HashDigest.hpp>
#include <Nazara/Core/ByteArray.hpp>
namespace Nz
{
@@ -21,12 +21,12 @@ namespace Nz
HashCRC32(UInt32 polynomial = 0x04c11db7);
virtual ~HashCRC32();
void Append(const UInt8* data, unsigned int len);
void Begin();
HashDigest End();
void Append(const UInt8* data, unsigned int len) override;
void Begin() override;
ByteArray End() override;
static unsigned int GetDigestLength();
static String GetHashName();
unsigned int GetDigestLength() const override;
const char* GetHashName() const override;
private:
HashCRC32_state* m_state;

View File

@@ -9,7 +9,7 @@
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/AbstractHash.hpp>
#include <Nazara/Core/HashDigest.hpp>
#include <Nazara/Core/ByteArray.hpp>
#include <Nazara/Core/String.hpp>
namespace Nz
@@ -22,12 +22,12 @@ namespace Nz
HashFletcher16();
virtual ~HashFletcher16();
void Append(const UInt8* data, unsigned int len);
void Begin();
HashDigest End();
void Append(const UInt8* data, unsigned int len) override;
void Begin() override;
ByteArray End() override;
static unsigned int GetDigestLength();
static String GetHashName();
unsigned int GetDigestLength() const override;
const char* GetHashName() const override;
private:
HashFletcher16_state* m_state;

View File

@@ -9,7 +9,7 @@
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/AbstractHash.hpp>
#include <Nazara/Core/HashDigest.hpp>
#include <Nazara/Core/ByteArray.hpp>
namespace Nz
{
@@ -21,12 +21,12 @@ namespace Nz
HashMD5();
virtual ~HashMD5();
void Append(const UInt8* data, unsigned int len);
void Begin();
HashDigest End();
void Append(const UInt8* data, unsigned int len) override;
void Begin() override;
ByteArray End() override;
static unsigned int GetDigestLength();
static String GetHashName();
unsigned int GetDigestLength() const override;
const char* GetHashName() const override;
private:
HashMD5_state* m_state;

View File

@@ -9,7 +9,7 @@
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/AbstractHash.hpp>
#include <Nazara/Core/HashDigest.hpp>
#include <Nazara/Core/ByteArray.hpp>
namespace Nz
{
@@ -21,12 +21,12 @@ namespace Nz
HashSHA1();
virtual ~HashSHA1();
void Append(const UInt8* data, unsigned int len);
void Begin();
HashDigest End();
void Append(const UInt8* data, unsigned int len) override;
void Begin() override;
ByteArray End() override;
static unsigned int GetDigestLength();
static String GetHashName();
unsigned int GetDigestLength() const override;
const char* GetHashName() const override;
private:
SHA_CTX* m_state;

View File

@@ -9,7 +9,7 @@
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/AbstractHash.hpp>
#include <Nazara/Core/HashDigest.hpp>
#include <Nazara/Core/ByteArray.hpp>
namespace Nz
{
@@ -21,12 +21,12 @@ namespace Nz
HashSHA224();
virtual ~HashSHA224();
void Append(const UInt8* data, unsigned int len);
void Begin();
HashDigest End();
void Append(const UInt8* data, unsigned int len) override;
void Begin() override;
ByteArray End() override;
static unsigned int GetDigestLength();
static String GetHashName();
unsigned int GetDigestLength() const override;
const char* GetHashName() const override;
private:
SHA_CTX* m_state;

View File

@@ -9,7 +9,7 @@
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/AbstractHash.hpp>
#include <Nazara/Core/HashDigest.hpp>
#include <Nazara/Core/ByteArray.hpp>
namespace Nz
{
@@ -21,12 +21,12 @@ namespace Nz
HashSHA256();
virtual ~HashSHA256();
void Append(const UInt8* data, unsigned int len);
void Begin();
HashDigest End();
void Append(const UInt8* data, unsigned int len) override;
void Begin() override;
ByteArray End() override;
static unsigned int GetDigestLength();
static String GetHashName();
unsigned int GetDigestLength() const override;
const char* GetHashName() const override;
private:
SHA_CTX* m_state;

View File

@@ -9,7 +9,7 @@
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/AbstractHash.hpp>
#include <Nazara/Core/HashDigest.hpp>
#include <Nazara/Core/ByteArray.hpp>
namespace Nz
{
@@ -21,12 +21,12 @@ namespace Nz
HashSHA384();
virtual ~HashSHA384();
void Append(const UInt8* data, unsigned int len);
void Begin();
HashDigest End();
void Append(const UInt8* data, unsigned int len) override;
void Begin() override;
ByteArray End() override;
static unsigned int GetDigestLength();
static String GetHashName();
unsigned int GetDigestLength() const override;
const char* GetHashName() const override;
private:
SHA_CTX* m_state;

View File

@@ -9,7 +9,7 @@
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/AbstractHash.hpp>
#include <Nazara/Core/HashDigest.hpp>
#include <Nazara/Core/ByteArray.hpp>
namespace Nz
{
@@ -21,12 +21,12 @@ namespace Nz
HashSHA512();
virtual ~HashSHA512();
void Append(const UInt8* data, unsigned int len);
void Begin();
HashDigest End();
void Append(const UInt8* data, unsigned int len) override;
void Begin() override;
ByteArray End() override;
static unsigned int GetDigestLength();
static String GetHashName();
unsigned int GetDigestLength() const override;
const char* GetHashName() const override;
private:
SHA_CTX* m_state;

View File

@@ -7,7 +7,7 @@
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/AbstractHash.hpp>
#include <Nazara/Core/HashDigest.hpp>
#include <Nazara/Core/ByteArray.hpp>
namespace Nz
{
@@ -19,12 +19,12 @@ namespace Nz
HashWhirlpool();
virtual ~HashWhirlpool();
void Append(const UInt8* data, unsigned int len);
void Begin();
HashDigest End();
void Append(const UInt8* data, unsigned int len) override;
void Begin() override;
ByteArray End() override;
static unsigned int GetDigestLength();
static String GetHashName();
unsigned int GetDigestLength() const;
const char* GetHashName() const;
private:
HashWhirlpool_state* m_state;

View File

@@ -1,56 +0,0 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_HASHDIGEST_HPP
#define NAZARA_HASHDIGEST_HPP
///TODO: Remplacer par ByteArray
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/String.hpp>
#include <iosfwd>
namespace Nz
{
class NAZARA_CORE_API HashDigest
{
public:
HashDigest();
HashDigest(const String& hashName, const UInt8* digest, unsigned int length);
HashDigest(const HashDigest& rhs);
HashDigest(HashDigest&& rhs) noexcept;
~HashDigest();
bool IsValid() const;
const UInt8* GetDigest() const;
unsigned int GetDigestLength() const;
String GetHashName() const;
String ToHex() const;
UInt8 operator[](unsigned int pos) const;
HashDigest& operator=(const HashDigest& rhs);
HashDigest& operator=(HashDigest&& rhs) noexcept;
bool operator==(const HashDigest& rhs) const;
bool operator!=(const HashDigest& rhs) const;
bool operator<(const HashDigest& rhs) const;
bool operator<=(const HashDigest& rhs) const;
bool operator>(const HashDigest& rhs) const;
bool operator>=(const HashDigest& rhs) const;
NAZARA_CORE_API friend std::ostream& operator<<(std::ostream& out, const HashDigest& string);
private:
String m_hashName;
UInt8* m_digest;
unsigned int m_digestLength;
};
}
#endif // NAZARA_HASHDIGEST_HPP

View File

@@ -1,39 +0,0 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef HASHABLE_HPP_INCLUDED
#define HASHABLE_HPP_INCLUDED
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Enums.hpp>
namespace Nz
{
class AbstractHash;
class HashDigest;
class NAZARA_CORE_API Hashable
{
friend class Hash;
public:
Hashable() = default;
Hashable(const Hashable&) = default;
Hashable(Hashable&&) = default;
virtual ~Hashable();
HashDigest GetHash(HashType hash) const;
HashDigest GetHash(AbstractHash* impl) const;
Hashable& operator=(const Hashable&) = default;
Hashable& operator=(Hashable&&) = default;
private:
virtual bool FillHash(AbstractHash* impl) const = 0;
};
}
#endif // HASHABLE_HPP_INCLUDED

View File

@@ -8,7 +8,7 @@
#define NAZARA_STRING_HPP
#include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Hashable.hpp>
#include <Nazara/Core/Algorithm.hpp>
#include <atomic>
#include <iosfwd>
#include <memory>
@@ -20,7 +20,7 @@ namespace Nz
class AbstractHash;
class HashDigest;
class NAZARA_CORE_API String : public Hashable
class NAZARA_CORE_API String
{
public:
enum Flags
@@ -306,7 +306,6 @@ namespace Nz
String(std::shared_ptr<SharedString>&& sharedString);
void EnsureOwnership(bool discardContent = false);
bool FillHash(AbstractHash* hash) const;
inline void ReleaseString();
static const std::shared_ptr<SharedString>& GetEmptyString();
@@ -324,6 +323,9 @@ namespace Nz
std::unique_ptr<char[]> string;
};
};
template<>
struct Hashable<String>;
}
namespace std
@@ -331,6 +333,9 @@ namespace std
NAZARA_CORE_API istream& getline(istream& is, Nz::String& str);
NAZARA_CORE_API istream& getline(istream& is, Nz::String& str, char delim);
NAZARA_CORE_API void swap(Nz::String& lhs, Nz::String& rhs);
template<>
struct hash<Nz::String>;
}
#include <Nazara/Core/String.inl>

View File

@@ -2,6 +2,7 @@
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/AbstractHash.hpp>
#include <Nazara/Core/Debug.hpp>
namespace Nz
@@ -37,6 +38,16 @@ namespace Nz
{
string[strSize] = '\0';
}
template<>
struct Hashable<String>
{
bool operator()(const String& str, AbstractHash* hash) const
{
hash->Append(reinterpret_cast<const UInt8*>(str.GetConstBuffer()), str.GetSize());
return true;
}
};
}
namespace std