diff --git a/include/Nazara/Core/Algorithm.hpp b/include/Nazara/Core/Algorithm.hpp index ae30f5065..5f8b8aa7f 100644 --- a/include/Nazara/Core/Algorithm.hpp +++ b/include/Nazara/Core/Algorithm.hpp @@ -27,11 +27,11 @@ namespace Nz template std::size_t CountOf(const T& c); template void HashCombine(std::size_t& seed, const T& v); - template - struct PointedType - { - using type = void; //< FIXME: I can't make SFINAE work - }; + template + struct PointedType + { + using type = void; //< FIXME: I can't make SFINAE work + }; template struct TypeTag {}; diff --git a/include/Nazara/Core/Algorithm.inl b/include/Nazara/Core/Algorithm.inl index c66bdb046..a9855c62c 100644 --- a/include/Nazara/Core/Algorithm.inl +++ b/include/Nazara/Core/Algorithm.inl @@ -30,6 +30,16 @@ namespace Nz } } + /*! + * \brief Applies the tuple to the function + * \return The result of the function + * + * \param fn Function + * \param t Tuple of arguments for the function + * + * \see Apply + */ + template auto Apply(F&& fn, Tuple&& t) { @@ -38,6 +48,17 @@ namespace Nz return Detail::ApplyImplFunc(std::forward(fn), std::forward(t), std::make_index_sequence()); } + /*! + * \brief Applies the tuple to the member function on an object + * \return The result of the member function called + * + * \param object Object of a class + * \param fn Member function + * \param t Tuple of arguments for the member function + * + * \see Apply + */ + template auto Apply(O& object, F&& fn, Tuple&& t) { @@ -46,15 +67,39 @@ namespace Nz return Detail::ApplyImplMethod(object, std::forward(fn), std::forward(t), std::make_index_sequence()); } + /*! + * \brief Computes the hash of a hashable object + * \return A bytearray which represents the hash + * + * \param hash Enumeration of type HashType + * \param v Object to hash, must be convertible to "Nz::String" + * + * \see ComputeHash + */ + template ByteArray ComputeHash(HashType hash, const T& v) { return ComputeHash(AbstractHash::Get(hash).get(), v); } + /*! + * \brief Computes the hash of a hashable object + * \return A bytearray which represents the hash + * + * \param hash Pointer to abstract hash + * \param v Object to hash, must be convertible to "Nz::String" + * + * \remark Produce a NazaraAssert if pointer to Abstracthash is invalid + * + * \see ComputeHash + */ + template ByteArray ComputeHash(AbstractHash* hash, const T& v) { + NazaraAssert(hash != nullptr, "Invalid abstracthash pointer"); + hash->Begin(); HashAppend(hash, v); @@ -62,19 +107,44 @@ namespace Nz return hash->End(); } - template + /*! + * \brief Returns the number of elements in a C-array + * \return The number of elements + * + * \param name C-array + * + * \see CountOf + */ + + template constexpr std::size_t CountOf(T(&name)[N]) noexcept { return N; } - template + /*! + * \brief Returns the number of elements in a container + * \return The number of elements + * + * \param c Container with the member function "size()" + * + * \see CountOf + */ + + template std::size_t CountOf(const T& c) { return c.size(); } - // Algorithme venant de CityHash par Google + /*! + * \brief Combines two hash in one + * + * \param seed First value that will be modified (expected to be 64bits) + * \param v Second value to hash + */ + + // Algorithm from CityHash by Google // http://stackoverflow.com/questions/8513911/how-to-create-a-good-hash-combine-with-64-bit-output-inspired-by-boosthash-co template void HashCombine(std::size_t& seed, const T& v) @@ -91,10 +161,20 @@ namespace Nz seed = static_cast(b * kMul); } - template struct PointedType {typedef T type;}; - template struct PointedType {typedef T type;}; - template struct PointedType {typedef T type;}; - template struct PointedType {typedef T type;}; + template struct PointedType {typedef T type;}; + template struct PointedType {typedef T type;}; + template struct PointedType {typedef T type;}; + template struct PointedType {typedef T type;}; + + /*! + * \brief Serializes a boolean + * \return true if serialization succedeed + * + * \param context Context for the serialization + * \param value Boolean to serialize + * + * \see Serialize, Unserialize + */ inline bool Serialize(SerializationContext& context, bool value) { @@ -113,6 +193,16 @@ namespace Nz return true; } + /*! + * \brief Serializes an arithmetic type + * \return true if serialization succedeed + * + * \param context Context for the serialization + * \param value Arithmetic type to serialize + * + * \see Serialize, Unserialize + */ + template std::enable_if_t::value, bool> Serialize(SerializationContext& context, T value) { @@ -131,6 +221,16 @@ namespace Nz return context.stream->Write(&value, sizeof(T)) == sizeof(T); } + /*! + * \brief Unserializes a boolean + * \return true if unserialization succedeed + * + * \param context Context for the unserialization + * \param value Pointer to boolean to unserialize + * + * \see Serialize, Unserialize + */ + inline bool Unserialize(SerializationContext& context, bool* value) { if (context.currentBitPos == 8) @@ -149,6 +249,18 @@ namespace Nz return true; } + /*! + * \brief Unserializes an arithmetic type + * \return true if unserialization succedeed + * + * \param context Context for the unserialization + * \param value Pointer to arithmetic type to serialize + * + * \remark Produce a NazaraAssert if pointer to value is invalid + * + * \see Serialize, Unserialize + */ + template std::enable_if_t::value, bool> Unserialize(SerializationContext& context, T* value) { diff --git a/tests/Engine/Core/AlgorithmCore.cpp b/tests/Engine/Core/AlgorithmCore.cpp new file mode 100644 index 000000000..8aff5cb24 --- /dev/null +++ b/tests/Engine/Core/AlgorithmCore.cpp @@ -0,0 +1,40 @@ +#include +#include + +#include + +#include + +TEST_CASE("Apply", "[CORE][ALGORITHM]") +{ + SECTION("Apply lambda to two vector2") + { + Nz::Vector2 vector = Nz::Vector2::Unit(); + auto lambda = [](const Nz::Vector2& vec1, const Nz::Vector2& vec2) + { + return vec1 + vec2; + }; + + Nz::Vector2 result = Nz::Apply(lambda, std::make_tuple(vector, vector)); + + REQUIRE(result == (Nz::Vector2::Unit() * 2)); + } + + SECTION("Apply member function to vector2") + { + Nz::Vector2 vector = Nz::Vector2::Unit(); + + int result = Nz::Apply(vector, &Nz::Vector2::Distance, std::make_tuple(vector)); + + REQUIRE(result == 0); + } +} + +TEST_CASE("ComputeHash", "[CORE][ALGORITHM]") +{ + SECTION("Compute hash of '0'") + { + auto result = Nz::ComputeHash(Nz::HashType_SHA512, "1234"); + REQUIRE(result.ToHex().ToUpper() == "D404559F602EAB6FD602AC7680DACBFAADD13630335E951F097AF3900E9DE176B6DB28512F2E000B9D04FBA5133E8B1C6E8DF59DB3A8AB9D60BE4B97CC9E81DB"); + } +}