// 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 // http://stackoverflow.com/questions/687490/c0x-how-do-i-expand-a-tuple-into-variadic-template-function-arguments // Merci à Ryan "FullMetal Alchemist" Lahfa // Merci aussi à Freedom de siteduzero.com #include #include #include #include #include namespace Nz { namespace Detail { // http://www.cppsamples.com/common-tasks/apply-tuple-to-function.html template auto ApplyImplFunc(F&& fn, Tuple&& t, std::index_sequence) { return std::forward(fn)(std::get(std::forward(t))...); } template auto ApplyImplMethod(O& object, F&& fn, Tuple&& t, std::index_sequence) { return (object .* std::forward(fn))(std::get(std::forward(t))...); } } template auto Apply(F&& fn, Tuple&& t) { constexpr std::size_t tSize = std::tuple_size::type>::value; return Detail::ApplyImplFunc(std::forward(fn), std::forward(t), std::make_index_sequence()); } template auto Apply(O& object, F&& fn, Tuple&& t) { constexpr std::size_t tSize = std::tuple_size::type>::value; return Detail::ApplyImplMethod(object, std::forward(fn), std::forward(t), std::make_index_sequence()); } template ByteArray ComputeHash(HashType hash, const T& v) { return ComputeHash(AbstractHash::Get(hash).get(), v); } template ByteArray ComputeHash(AbstractHash* hash, const T& v) { hash->Begin(); HashAppend(hash, v); 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 void HashCombine(std::size_t& seed, const T& v) { const UInt64 kMul = 0x9ddfea08eb382d69ULL; std::hash hasher; UInt64 a = (hasher(v) ^ seed) * kMul; a ^= (a >> 47); UInt64 b = (seed ^ a) * kMul; b ^= (b >> 47); seed = static_cast(b * kMul); } inline bool Serialize(SerializationContext& context, bool value) { ///TODO: Handle bits writing (Serializing 8 bits should only use one byte) UInt8 buffer = (value) ? 1 : 0; return context.stream->Write(&buffer, 1) == 1; } template std::enable_if_t::value, bool> Serialize(SerializationContext& context, T value) { if (context.endianness != Endianness_Unknown && context.endianness != GetPlatformEndianness()) SwapBytes(&value, sizeof(T)); return context.stream->Write(&value, sizeof(T)) == sizeof(T); } inline bool Unserialize(UnserializationContext& context, bool* value) { NazaraAssert(value, "Invalid data pointer"); UInt8 buffer; if (context.stream->Read(&buffer, 1) == 1) { *value = (buffer == 1); return true; } else return false; } template std::enable_if_t::value, bool> Unserialize(UnserializationContext& context, T* value) { NazaraAssert(value, "Invalid data pointer"); if (context.stream->Read(value, sizeof(T)) == sizeof(T)) { if (context.endianness != Endianness_Unknown && context.endianness != GetPlatformEndianness()) SwapBytes(value, sizeof(T)); return true; } else return false; } } #include