Switch from Nz prefix to namespace Nz
What a huge commit Former-commit-id: 38ac5eebf70adc1180f571f6006192d28fb99897
This commit is contained in:
@@ -5,4 +5,7 @@
|
||||
#include <Nazara/Core/AbstractHash.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzAbstractHash::~NzAbstractHash() = default;
|
||||
namespace Nz
|
||||
{
|
||||
AbstractHash::~AbstractHash() = default;
|
||||
}
|
||||
|
||||
@@ -7,15 +7,18 @@
|
||||
#include <ostream>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const NzByteArray& byteArray)
|
||||
namespace Nz
|
||||
{
|
||||
out << byteArray.ToString();
|
||||
return out;
|
||||
}
|
||||
std::ostream& operator<<(std::ostream& out, const ByteArray& byteArray)
|
||||
{
|
||||
out << byteArray.ToString();
|
||||
return out;
|
||||
}
|
||||
|
||||
bool NzByteArray::FillHash(NzAbstractHash* hash) const
|
||||
{
|
||||
hash->Append(GetConstBuffer(), GetSize());
|
||||
bool ByteArray::FillHash(AbstractHash* hash) const
|
||||
{
|
||||
hash->Append(GetConstBuffer(), GetSize());
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,93 +21,96 @@
|
||||
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
namespace
|
||||
namespace Nz
|
||||
{
|
||||
nzUInt64 NzGetMicrosecondsLowPrecision()
|
||||
namespace Detail
|
||||
{
|
||||
return NzClockImplGetMilliseconds()*1000ULL;
|
||||
UInt64 GetMicrosecondsLowPrecision()
|
||||
{
|
||||
return ClockImplGetElapsedMilliseconds()*1000ULL;
|
||||
}
|
||||
|
||||
UInt64 GetElapsedMicrosecondsFirstRun()
|
||||
{
|
||||
if (ClockImplInitializeHighPrecision())
|
||||
GetElapsedMicroseconds = ClockImplGetElapsedMicroseconds;
|
||||
else
|
||||
GetElapsedMicroseconds = GetMicrosecondsLowPrecision;
|
||||
|
||||
return GetElapsedMicroseconds();
|
||||
}
|
||||
}
|
||||
|
||||
nzUInt64 NzGetMicrosecondsFirstRun()
|
||||
Clock::Clock(UInt64 startingValue, bool paused) :
|
||||
m_elapsedTime(startingValue),
|
||||
m_refTime(GetElapsedMicroseconds()),
|
||||
m_paused(paused)
|
||||
{
|
||||
if (NzClockImplInitializeHighPrecision())
|
||||
NzGetMicroseconds = NzClockImplGetMicroseconds;
|
||||
}
|
||||
|
||||
float Clock::GetSeconds() const
|
||||
{
|
||||
return GetMicroseconds()/1000000.f;
|
||||
}
|
||||
|
||||
UInt64 Clock::GetMicroseconds() const
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
UInt64 elapsedMicroseconds = m_elapsedTime;
|
||||
if (!m_paused)
|
||||
elapsedMicroseconds += (GetElapsedMicroseconds() - m_refTime);
|
||||
|
||||
return elapsedMicroseconds;
|
||||
}
|
||||
|
||||
UInt64 Clock::GetMilliseconds() const
|
||||
{
|
||||
return GetMicroseconds()/1000;
|
||||
}
|
||||
|
||||
bool Clock::IsPaused() const
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
return m_paused;
|
||||
}
|
||||
|
||||
void Clock::Pause()
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
if (!m_paused)
|
||||
{
|
||||
m_elapsedTime += GetElapsedMicroseconds() - m_refTime;
|
||||
m_paused = true;
|
||||
}
|
||||
else
|
||||
NzGetMicroseconds = NzGetMicrosecondsLowPrecision;
|
||||
|
||||
return NzGetMicroseconds();
|
||||
NazaraWarning("Clock is already paused, ignoring...");
|
||||
}
|
||||
}
|
||||
|
||||
NzClock::NzClock(nzUInt64 startingValue, bool paused) :
|
||||
m_elapsedTime(startingValue),
|
||||
m_refTime(NzGetMicroseconds()),
|
||||
m_paused(paused)
|
||||
{
|
||||
}
|
||||
|
||||
float NzClock::GetSeconds() const
|
||||
{
|
||||
return GetMicroseconds()/1000000.f;
|
||||
}
|
||||
|
||||
nzUInt64 NzClock::GetMicroseconds() const
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
nzUInt64 elapsedMicroseconds = m_elapsedTime;
|
||||
if (!m_paused)
|
||||
elapsedMicroseconds += (NzGetMicroseconds() - m_refTime);
|
||||
|
||||
return elapsedMicroseconds;
|
||||
}
|
||||
|
||||
nzUInt64 NzClock::GetMilliseconds() const
|
||||
{
|
||||
return GetMicroseconds()/1000;
|
||||
}
|
||||
|
||||
bool NzClock::IsPaused() const
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
return m_paused;
|
||||
}
|
||||
|
||||
void NzClock::Pause()
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
if (!m_paused)
|
||||
void Clock::Restart()
|
||||
{
|
||||
m_elapsedTime += NzGetMicroseconds()-m_refTime;
|
||||
m_paused = true;
|
||||
}
|
||||
else
|
||||
NazaraWarning("Clock is already paused, ignoring...");
|
||||
}
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
void NzClock::Restart()
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
m_elapsedTime = 0;
|
||||
m_refTime = NzGetMicroseconds();
|
||||
m_paused = false;
|
||||
}
|
||||
|
||||
void NzClock::Unpause()
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
if (m_paused)
|
||||
{
|
||||
m_refTime = NzGetMicroseconds();
|
||||
m_elapsedTime = 0;
|
||||
m_refTime = GetElapsedMicroseconds();
|
||||
m_paused = false;
|
||||
}
|
||||
else
|
||||
NazaraWarning("Clock is not paused, ignoring...");
|
||||
}
|
||||
|
||||
NzClockFunction NzGetMicroseconds = NzGetMicrosecondsFirstRun;
|
||||
NzClockFunction NzGetMilliseconds = NzClockImplGetMilliseconds;
|
||||
void Clock::Unpause()
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
if (m_paused)
|
||||
{
|
||||
m_refTime = GetElapsedMicroseconds();
|
||||
m_paused = false;
|
||||
}
|
||||
else
|
||||
NazaraWarning("Clock is not paused, ignoring...");
|
||||
}
|
||||
|
||||
ClockFunction GetElapsedMicroseconds = Detail::GetElapsedMicrosecondsFirstRun;
|
||||
ClockFunction GetElapsedMilliseconds = ClockImplGetElapsedMilliseconds;
|
||||
}
|
||||
|
||||
@@ -5,12 +5,15 @@
|
||||
#include <Nazara/Core/Color.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
const NzColor NzColor::Black(0, 0, 0);
|
||||
const NzColor NzColor::Blue(0, 0, 255);
|
||||
const NzColor NzColor::Cyan(0, 255, 255);
|
||||
const NzColor NzColor::Green(0, 255, 0);
|
||||
const NzColor NzColor::Magenta(255, 0, 255);
|
||||
const NzColor NzColor::Orange(255, 165, 0);
|
||||
const NzColor NzColor::Red(255, 0, 0);
|
||||
const NzColor NzColor::Yellow(255, 255, 0);
|
||||
const NzColor NzColor::White(255, 255, 255);
|
||||
namespace Nz
|
||||
{
|
||||
const Color Color::Black(0, 0, 0);
|
||||
const Color Color::Blue(0, 0, 255);
|
||||
const Color Color::Cyan(0, 255, 255);
|
||||
const Color Color::Green(0, 255, 0);
|
||||
const Color Color::Magenta(255, 0, 255);
|
||||
const Color Color::Orange(255, 165, 0);
|
||||
const Color Color::Red(255, 0, 0);
|
||||
const Color Color::Yellow(255, 255, 0);
|
||||
const Color Color::White(255, 255, 255);
|
||||
}
|
||||
|
||||
@@ -16,34 +16,37 @@
|
||||
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzConditionVariable::NzConditionVariable()
|
||||
namespace Nz
|
||||
{
|
||||
m_impl = new NzConditionVariableImpl;
|
||||
}
|
||||
ConditionVariable::ConditionVariable()
|
||||
{
|
||||
m_impl = new ConditionVariableImpl;
|
||||
}
|
||||
|
||||
NzConditionVariable::~NzConditionVariable()
|
||||
{
|
||||
delete m_impl;
|
||||
}
|
||||
ConditionVariable::~ConditionVariable()
|
||||
{
|
||||
delete m_impl;
|
||||
}
|
||||
|
||||
void NzConditionVariable::Signal()
|
||||
{
|
||||
m_impl->Signal();
|
||||
}
|
||||
void ConditionVariable::Signal()
|
||||
{
|
||||
m_impl->Signal();
|
||||
}
|
||||
|
||||
void NzConditionVariable::SignalAll()
|
||||
{
|
||||
m_impl->SignalAll();
|
||||
}
|
||||
void ConditionVariable::SignalAll()
|
||||
{
|
||||
m_impl->SignalAll();
|
||||
}
|
||||
|
||||
void NzConditionVariable::Wait(NzMutex* mutex)
|
||||
{
|
||||
NazaraAssert(mutex != nullptr, "Mutex must be valid");
|
||||
m_impl->Wait(mutex->m_impl);
|
||||
}
|
||||
void ConditionVariable::Wait(Mutex* mutex)
|
||||
{
|
||||
NazaraAssert(mutex != nullptr, "Mutex must be valid");
|
||||
m_impl->Wait(mutex->m_impl);
|
||||
}
|
||||
|
||||
bool NzConditionVariable::Wait(NzMutex* mutex, nzUInt32 timeout)
|
||||
{
|
||||
NazaraAssert(mutex != nullptr, "Mutex must be valid");
|
||||
return m_impl->Wait(mutex->m_impl, timeout);
|
||||
bool ConditionVariable::Wait(Mutex* mutex, UInt32 timeout)
|
||||
{
|
||||
NazaraAssert(mutex != nullptr, "Mutex must be valid");
|
||||
return m_impl->Wait(mutex->m_impl, timeout);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,44 +11,47 @@
|
||||
#include <Nazara/Core/TaskScheduler.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
bool NzCore::Initialize()
|
||||
namespace Nz
|
||||
{
|
||||
if (s_moduleReferenceCounter > 0)
|
||||
bool Core::Initialize()
|
||||
{
|
||||
if (s_moduleReferenceCounter > 0)
|
||||
{
|
||||
s_moduleReferenceCounter++;
|
||||
return true; // Déjà initialisé
|
||||
}
|
||||
|
||||
s_moduleReferenceCounter++;
|
||||
return true; // Déjà initialisé
|
||||
|
||||
NazaraNotice("Initialized: Core");
|
||||
return true;
|
||||
}
|
||||
|
||||
s_moduleReferenceCounter++;
|
||||
|
||||
NazaraNotice("Initialized: Core");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzCore::IsInitialized()
|
||||
{
|
||||
return s_moduleReferenceCounter != 0;
|
||||
}
|
||||
|
||||
void NzCore::Uninitialize()
|
||||
{
|
||||
if (s_moduleReferenceCounter != 1)
|
||||
bool Core::IsInitialized()
|
||||
{
|
||||
// Le module est soit encore utilisé, soit pas initialisé
|
||||
if (s_moduleReferenceCounter > 1)
|
||||
s_moduleReferenceCounter--;
|
||||
|
||||
return;
|
||||
return s_moduleReferenceCounter != 0;
|
||||
}
|
||||
|
||||
// Libération du module
|
||||
s_moduleReferenceCounter = 0;
|
||||
void Core::Uninitialize()
|
||||
{
|
||||
if (s_moduleReferenceCounter != 1)
|
||||
{
|
||||
// Le module est soit encore utilisé, soit pas initialisé
|
||||
if (s_moduleReferenceCounter > 1)
|
||||
s_moduleReferenceCounter--;
|
||||
|
||||
NzHardwareInfo::Uninitialize();
|
||||
NzPluginManager::Uninitialize();
|
||||
NzTaskScheduler::Uninitialize();
|
||||
return;
|
||||
}
|
||||
|
||||
NazaraNotice("Uninitialized: Core");
|
||||
// Libération du module
|
||||
s_moduleReferenceCounter = 0;
|
||||
|
||||
HardwareInfo::Uninitialize();
|
||||
PluginManager::Uninitialize();
|
||||
TaskScheduler::Uninitialize();
|
||||
|
||||
NazaraNotice("Uninitialized: Core");
|
||||
}
|
||||
|
||||
unsigned int Core::s_moduleReferenceCounter = 0;
|
||||
}
|
||||
|
||||
unsigned int NzCore::s_moduleReferenceCounter = 0;
|
||||
|
||||
@@ -10,22 +10,22 @@
|
||||
|
||||
void* operator new(std::size_t size)
|
||||
{
|
||||
return NzMemoryManager::Allocate(size, false);
|
||||
return Nz::MemoryManager::Allocate(size, false);
|
||||
}
|
||||
|
||||
void* operator new[](std::size_t size)
|
||||
{
|
||||
return NzMemoryManager::Allocate(size, true);
|
||||
return Nz::MemoryManager::Allocate(size, true);
|
||||
}
|
||||
|
||||
void operator delete(void* pointer) noexcept
|
||||
{
|
||||
NzMemoryManager::Free(pointer, false);
|
||||
Nz::MemoryManager::Free(pointer, false);
|
||||
}
|
||||
|
||||
void operator delete[](void* pointer) noexcept
|
||||
{
|
||||
NzMemoryManager::Free(pointer, true);
|
||||
Nz::MemoryManager::Free(pointer, true);
|
||||
}
|
||||
|
||||
#endif // NAZARA_CORE_MANAGE_MEMORY
|
||||
|
||||
@@ -13,24 +13,24 @@
|
||||
|
||||
void* operator new(std::size_t size, const char* file, unsigned int line)
|
||||
{
|
||||
return NzMemoryManager::Allocate(size, false, file, line);
|
||||
return Nz::MemoryManager::Allocate(size, false, file, line);
|
||||
}
|
||||
|
||||
void* operator new[](std::size_t size, const char* file, unsigned int line)
|
||||
{
|
||||
return NzMemoryManager::Allocate(size, true, file, line);
|
||||
return Nz::MemoryManager::Allocate(size, true, file, line);
|
||||
}
|
||||
|
||||
void operator delete(void* ptr, const char* file, unsigned int line) noexcept
|
||||
{
|
||||
NzMemoryManager::NextFree(file, line);
|
||||
NzMemoryManager::Free(ptr, false);
|
||||
Nz::MemoryManager::NextFree(file, line);
|
||||
Nz::MemoryManager::Free(ptr, false);
|
||||
}
|
||||
|
||||
void operator delete[](void* ptr, const char* file, unsigned int line) noexcept
|
||||
{
|
||||
NzMemoryManager::NextFree(file, line);
|
||||
NzMemoryManager::Free(ptr, true);
|
||||
Nz::MemoryManager::NextFree(file, line);
|
||||
Nz::MemoryManager::Free(ptr, true);
|
||||
}
|
||||
|
||||
#endif // NAZARA_CORE_MANAGE_MEMORY
|
||||
|
||||
@@ -24,364 +24,367 @@
|
||||
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
namespace
|
||||
namespace Nz
|
||||
{
|
||||
/*thread_local*/ NzString currentPath(NzDirectoryImpl::GetCurrent());
|
||||
}
|
||||
|
||||
NzDirectory::NzDirectory() :
|
||||
m_pattern('*'),
|
||||
m_impl(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
NzDirectory::NzDirectory(const NzString& dirPath) :
|
||||
m_dirPath(dirPath),
|
||||
m_pattern('*'),
|
||||
m_impl(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
NzDirectory::~NzDirectory()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
void NzDirectory::Close()
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
if (m_impl)
|
||||
namespace
|
||||
{
|
||||
m_impl->Close();
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool NzDirectory::Exists() const
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
if (IsOpen())
|
||||
return true; // Le fichier est ouvert, donc il existe
|
||||
else
|
||||
return Exists(m_dirPath);
|
||||
}
|
||||
|
||||
NzString NzDirectory::GetPath() const
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
return m_dirPath;
|
||||
}
|
||||
|
||||
NzString NzDirectory::GetPattern() const
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
return m_pattern;
|
||||
}
|
||||
|
||||
NzString NzDirectory::GetResultName() const
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Directory not opened");
|
||||
return NzString();
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->GetResultName();
|
||||
}
|
||||
|
||||
NzString NzDirectory::GetResultPath() const
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Directory not opened");
|
||||
return NzString();
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_dirPath + NAZARA_DIRECTORY_SEPARATOR + m_impl->GetResultName();
|
||||
}
|
||||
|
||||
nzUInt64 NzDirectory::GetResultSize() const
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Directory not opened");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->GetResultSize();
|
||||
}
|
||||
|
||||
bool NzDirectory::IsOpen() const
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
return m_impl != nullptr;
|
||||
}
|
||||
|
||||
bool NzDirectory::IsResultDirectory() const
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Directory not opened");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->IsResultDirectory();
|
||||
}
|
||||
|
||||
bool NzDirectory::NextResult(bool skipDots)
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Directory not opened");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
NzString name;
|
||||
do
|
||||
{
|
||||
if (!m_impl->NextResult())
|
||||
return false;
|
||||
|
||||
name = m_impl->GetResultName();
|
||||
|
||||
if (skipDots && (name == '.' || name == ".."))
|
||||
continue;
|
||||
|
||||
if (name.Match(m_pattern))
|
||||
break;
|
||||
}
|
||||
while (true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzDirectory::Open()
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
Close();
|
||||
|
||||
if (!Exists(m_dirPath))
|
||||
return false;
|
||||
|
||||
m_impl = new NzDirectoryImpl(this);
|
||||
if (!m_impl->Open(m_dirPath))
|
||||
{
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
|
||||
return false;
|
||||
thread_local String currentPath(DirectoryImpl::GetCurrent());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzDirectory::SetPath(const NzString& dirPath)
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
Close();
|
||||
|
||||
m_dirPath = NzFile::AbsolutePath(dirPath);
|
||||
}
|
||||
|
||||
void NzDirectory::SetPattern(const NzString& pattern)
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
m_pattern = pattern;
|
||||
}
|
||||
|
||||
bool NzDirectory::Copy(const NzString& sourcePath, const NzString& destPath)
|
||||
{
|
||||
if (sourcePath.IsEmpty() || destPath.IsEmpty())
|
||||
return false;
|
||||
|
||||
NzString dirPath(sourcePath);
|
||||
NzString dest(NzFile::NormalizePath(destPath));
|
||||
|
||||
if (!Create(destPath, true))
|
||||
Directory::Directory() :
|
||||
m_pattern('*'),
|
||||
m_impl(nullptr)
|
||||
{
|
||||
NazaraError("Unable to create \"" + destPath + '"');
|
||||
return false;
|
||||
}
|
||||
|
||||
NzDirectory dir(dirPath);
|
||||
if (!dir.Open())
|
||||
Directory::Directory(const String& dirPath) :
|
||||
m_dirPath(dirPath),
|
||||
m_pattern('*'),
|
||||
m_impl(nullptr)
|
||||
{
|
||||
NazaraError("Unable to open \"" + destPath + '"');
|
||||
return false;
|
||||
}
|
||||
|
||||
while (dir.NextResult(true))
|
||||
Directory::~Directory()
|
||||
{
|
||||
if (dir.IsResultDirectory())
|
||||
Close();
|
||||
}
|
||||
|
||||
void Directory::Close()
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
if (m_impl)
|
||||
{
|
||||
if (!Copy(dir.GetResultPath(), dest + NAZARA_DIRECTORY_SEPARATOR + dir.GetResultName()))
|
||||
return false;
|
||||
}
|
||||
else if (!NzFile::Copy(dir.GetResultPath(), dest + NAZARA_DIRECTORY_SEPARATOR + dir.GetResultName()))
|
||||
{
|
||||
NazaraError("Failed to copy \"" + dir.GetResultPath() + "\" to \"" + dest + NAZARA_DIRECTORY_SEPARATOR + dir.GetResultName() + '"');
|
||||
return false;
|
||||
m_impl->Close();
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
dir.Close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzDirectory::Create(const NzString& dirPath, bool recursive)
|
||||
{
|
||||
if (dirPath.IsEmpty())
|
||||
return false;
|
||||
|
||||
if (recursive)
|
||||
bool Directory::Exists() const
|
||||
{
|
||||
NzString path = NzFile::NormalizePath(dirPath);
|
||||
unsigned int foundPos = path.Find(NAZARA_DIRECTORY_SEPARATOR);
|
||||
if (foundPos == NzString::npos)
|
||||
return false;
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
#ifdef NAZARA_PLATFORM_WINDOWS
|
||||
// Contrairement au disque (Ex: "C:"), le chemin réseau n'est pas considéré comme un dossier (Ex: "\\Laptop")
|
||||
if (path.Match("\\\\*"))
|
||||
if (IsOpen())
|
||||
return true; // Le fichier est ouvert, donc il existe
|
||||
else
|
||||
return Exists(m_dirPath);
|
||||
}
|
||||
|
||||
String Directory::GetPath() const
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
return m_dirPath;
|
||||
}
|
||||
|
||||
String Directory::GetPattern() const
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
return m_pattern;
|
||||
}
|
||||
|
||||
String Directory::GetResultName() const
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
foundPos = path.Find('\\', 2);
|
||||
if (foundPos == NzString::npos)
|
||||
return false;
|
||||
|
||||
foundPos = path.Find('\\', foundPos+1);
|
||||
if (foundPos == NzString::npos)
|
||||
return false;
|
||||
NazaraError("Directory not opened");
|
||||
return String();
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->GetResultName();
|
||||
}
|
||||
|
||||
String Directory::GetResultPath() const
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Directory not opened");
|
||||
return String();
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_dirPath + NAZARA_DIRECTORY_SEPARATOR + m_impl->GetResultName();
|
||||
}
|
||||
|
||||
UInt64 Directory::GetResultSize() const
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Directory not opened");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->GetResultSize();
|
||||
}
|
||||
|
||||
bool Directory::IsOpen() const
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
return m_impl != nullptr;
|
||||
}
|
||||
|
||||
bool Directory::IsResultDirectory() const
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Directory not opened");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->IsResultDirectory();
|
||||
}
|
||||
|
||||
bool Directory::NextResult(bool skipDots)
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Directory not opened");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
String name;
|
||||
do
|
||||
{
|
||||
NzString p = path.SubString(0, foundPos);
|
||||
if (p.EndsWith(NAZARA_DIRECTORY_SEPARATOR))
|
||||
p = p.SubString(0, -2);
|
||||
|
||||
if (!NzDirectoryImpl::Exists(p) && !NzDirectoryImpl::Create(p))
|
||||
if (!m_impl->NextResult())
|
||||
return false;
|
||||
|
||||
if (foundPos == NzString::npos)
|
||||
break;
|
||||
name = m_impl->GetResultName();
|
||||
|
||||
foundPos = path.Find(NAZARA_DIRECTORY_SEPARATOR, foundPos+1);
|
||||
if (skipDots && (name == '.' || name == ".."))
|
||||
continue;
|
||||
|
||||
if (name.Match(m_pattern))
|
||||
break;
|
||||
}
|
||||
while (true);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return NzDirectoryImpl::Create(NzFile::NormalizePath(dirPath));
|
||||
}
|
||||
|
||||
bool NzDirectory::Exists(const NzString& dirPath)
|
||||
{
|
||||
if (dirPath.IsEmpty())
|
||||
return false;
|
||||
|
||||
return NzDirectoryImpl::Exists(NzFile::NormalizePath(dirPath));
|
||||
}
|
||||
|
||||
NzString NzDirectory::GetCurrent()
|
||||
{
|
||||
return currentPath;
|
||||
}
|
||||
|
||||
const char* NzDirectory::GetCurrentFileRelativeToEngine(const char* currentFile)
|
||||
{
|
||||
///FIXME: Est-ce que cette méthode est au bon endroit ?
|
||||
static int offset = -1;
|
||||
|
||||
if (offset < 0)
|
||||
bool Directory::Open()
|
||||
{
|
||||
const char* directoryFile = __FILE__;
|
||||
const char* ptr = std::strstr(directoryFile, "NazaraEngine/src/Nazara/Core/Directory.cpp");
|
||||
if (ptr)
|
||||
offset = ptr - directoryFile;
|
||||
else
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
Close();
|
||||
|
||||
if (!Exists(m_dirPath))
|
||||
return false;
|
||||
|
||||
m_impl = new DirectoryImpl(this);
|
||||
if (!m_impl->Open(m_dirPath))
|
||||
{
|
||||
ptr = std::strstr(directoryFile, "NazaraEngine\\src\\Nazara\\Core\\Directory.cpp");
|
||||
if (ptr)
|
||||
offset = ptr - directoryFile;
|
||||
else
|
||||
offset = 0;
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return ¤tFile[offset];
|
||||
}
|
||||
|
||||
bool NzDirectory::Remove(const NzString& dirPath, bool emptyDirectory)
|
||||
{
|
||||
if (dirPath.IsEmpty())
|
||||
return false;
|
||||
|
||||
if (emptyDirectory)
|
||||
void Directory::SetPath(const String& dirPath)
|
||||
{
|
||||
NzDirectory dir(dirPath);
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
Close();
|
||||
|
||||
m_dirPath = File::AbsolutePath(dirPath);
|
||||
}
|
||||
|
||||
void Directory::SetPattern(const String& pattern)
|
||||
{
|
||||
NazaraLock(m_mutex);
|
||||
|
||||
m_pattern = pattern;
|
||||
}
|
||||
|
||||
bool Directory::Copy(const String& sourcePath, const String& destPath)
|
||||
{
|
||||
if (sourcePath.IsEmpty() || destPath.IsEmpty())
|
||||
return false;
|
||||
|
||||
String dirPath(sourcePath);
|
||||
String dest(File::NormalizePath(destPath));
|
||||
|
||||
if (!Create(destPath, true))
|
||||
{
|
||||
NazaraError("Unable to create \"" + destPath + '"');
|
||||
return false;
|
||||
}
|
||||
|
||||
Directory dir(dirPath);
|
||||
if (!dir.Open())
|
||||
return NzDirectoryImpl::Remove(dirPath); // Si on n'arrive pas à ouvrir le dossier, on tente de le supprimer
|
||||
{
|
||||
NazaraError("Unable to open \"" + destPath + '"');
|
||||
return false;
|
||||
}
|
||||
|
||||
while (dir.NextResult(true))
|
||||
{
|
||||
if (dir.IsResultDirectory())
|
||||
{
|
||||
if (!Remove(dir.GetResultPath(), true))
|
||||
if (!Copy(dir.GetResultPath(), dest + NAZARA_DIRECTORY_SEPARATOR + dir.GetResultName()))
|
||||
return false;
|
||||
}
|
||||
else if (!NzFile::Delete(dir.GetResultPath()))
|
||||
else if (!File::Copy(dir.GetResultPath(), dest + NAZARA_DIRECTORY_SEPARATOR + dir.GetResultName()))
|
||||
{
|
||||
NazaraError(dir.GetResultPath());
|
||||
NazaraError("Failed to copy \"" + dir.GetResultPath() + "\" to \"" + dest + NAZARA_DIRECTORY_SEPARATOR + dir.GetResultName() + '"');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
dir.Close();
|
||||
}
|
||||
|
||||
return NzDirectoryImpl::Remove(NzFile::NormalizePath(dirPath));
|
||||
}
|
||||
|
||||
bool NzDirectory::SetCurrent(const NzString& dirPath)
|
||||
{
|
||||
NzString path = NzFile::AbsolutePath(dirPath);
|
||||
if (NzDirectoryImpl::Exists(path))
|
||||
{
|
||||
currentPath = path;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
bool Directory::Create(const String& dirPath, bool recursive)
|
||||
{
|
||||
if (dirPath.IsEmpty())
|
||||
return false;
|
||||
|
||||
if (recursive)
|
||||
{
|
||||
String path = File::NormalizePath(dirPath);
|
||||
unsigned int foundPos = path.Find(NAZARA_DIRECTORY_SEPARATOR);
|
||||
if (foundPos == String::npos)
|
||||
return false;
|
||||
|
||||
#ifdef NAZARA_PLATFORM_WINDOWS
|
||||
// Contrairement au disque (Ex: "C:"), le chemin réseau n'est pas considéré comme un dossier (Ex: "\\Laptop")
|
||||
if (path.Match("\\\\*"))
|
||||
{
|
||||
foundPos = path.Find('\\', 2);
|
||||
if (foundPos == String::npos)
|
||||
return false;
|
||||
|
||||
foundPos = path.Find('\\', foundPos+1);
|
||||
if (foundPos == String::npos)
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
do
|
||||
{
|
||||
String p = path.SubString(0, foundPos);
|
||||
if (p.EndsWith(NAZARA_DIRECTORY_SEPARATOR))
|
||||
p = p.SubString(0, -2);
|
||||
|
||||
if (!DirectoryImpl::Exists(p) && !DirectoryImpl::Create(p))
|
||||
return false;
|
||||
|
||||
if (foundPos == String::npos)
|
||||
break;
|
||||
|
||||
foundPos = path.Find(NAZARA_DIRECTORY_SEPARATOR, foundPos+1);
|
||||
}
|
||||
while (true);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return DirectoryImpl::Create(File::NormalizePath(dirPath));
|
||||
}
|
||||
|
||||
bool Directory::Exists(const String& dirPath)
|
||||
{
|
||||
if (dirPath.IsEmpty())
|
||||
return false;
|
||||
|
||||
return DirectoryImpl::Exists(File::NormalizePath(dirPath));
|
||||
}
|
||||
|
||||
String Directory::GetCurrent()
|
||||
{
|
||||
return currentPath;
|
||||
}
|
||||
|
||||
const char* Directory::GetCurrentFileRelativeToEngine(const char* currentFile)
|
||||
{
|
||||
///FIXME: Est-ce que cette méthode est au bon endroit ?
|
||||
static int offset = -1;
|
||||
|
||||
if (offset < 0)
|
||||
{
|
||||
const char* directoryFile = __FILE__;
|
||||
const char* ptr = std::strstr(directoryFile, "NazaraEngine/src/Nazara/Core/Directory.cpp");
|
||||
if (ptr)
|
||||
offset = ptr - directoryFile;
|
||||
else
|
||||
{
|
||||
ptr = std::strstr(directoryFile, "NazaraEngine\\src\\Nazara\\Core\\Directory.cpp");
|
||||
if (ptr)
|
||||
offset = ptr - directoryFile;
|
||||
else
|
||||
offset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return ¤tFile[offset];
|
||||
}
|
||||
|
||||
bool Directory::Remove(const String& dirPath, bool emptyDirectory)
|
||||
{
|
||||
if (dirPath.IsEmpty())
|
||||
return false;
|
||||
|
||||
if (emptyDirectory)
|
||||
{
|
||||
Directory dir(dirPath);
|
||||
if (!dir.Open())
|
||||
return DirectoryImpl::Remove(dirPath); // Si on n'arrive pas à ouvrir le dossier, on tente de le supprimer
|
||||
|
||||
while (dir.NextResult(true))
|
||||
{
|
||||
if (dir.IsResultDirectory())
|
||||
{
|
||||
if (!Remove(dir.GetResultPath(), true))
|
||||
return false;
|
||||
}
|
||||
else if (!File::Delete(dir.GetResultPath()))
|
||||
{
|
||||
NazaraError(dir.GetResultPath());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
dir.Close();
|
||||
}
|
||||
|
||||
return DirectoryImpl::Remove(File::NormalizePath(dirPath));
|
||||
}
|
||||
|
||||
bool Directory::SetCurrent(const String& dirPath)
|
||||
{
|
||||
String path = File::AbsolutePath(dirPath);
|
||||
if (DirectoryImpl::Exists(path))
|
||||
{
|
||||
currentPath = path;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,88 +23,91 @@
|
||||
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzDynLib::NzDynLib() :
|
||||
m_impl(nullptr)
|
||||
namespace Nz
|
||||
{
|
||||
}
|
||||
|
||||
NzDynLib::NzDynLib(NzDynLib&& lib) :
|
||||
m_lastError(std::move(lib.m_lastError)),
|
||||
m_impl(lib.m_impl)
|
||||
{
|
||||
lib.m_impl = nullptr;
|
||||
}
|
||||
|
||||
NzDynLib::~NzDynLib()
|
||||
{
|
||||
Unload();
|
||||
}
|
||||
|
||||
NzString NzDynLib::GetLastError() const
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
return m_lastError;
|
||||
}
|
||||
|
||||
NzDynLibFunc NzDynLib::GetSymbol(const NzString& symbol) const
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (!m_impl)
|
||||
DynLib::DynLib() :
|
||||
m_impl(nullptr)
|
||||
{
|
||||
NazaraError("Library not opened");
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->GetSymbol(symbol, &m_lastError);
|
||||
}
|
||||
|
||||
bool NzDynLib::IsLoaded() const
|
||||
{
|
||||
return m_impl != nullptr;
|
||||
}
|
||||
|
||||
bool NzDynLib::Load(const NzString& libraryPath)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
Unload();
|
||||
|
||||
std::unique_ptr<NzDynLibImpl> impl(new NzDynLibImpl(this));
|
||||
if (!impl->Load(libraryPath, &m_lastError))
|
||||
{
|
||||
NazaraError("Failed to load library: " + m_lastError);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_impl = impl.release();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzDynLib::Unload()
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
if (m_impl)
|
||||
DynLib::DynLib(DynLib&& lib) :
|
||||
m_lastError(std::move(lib.m_lastError)),
|
||||
m_impl(lib.m_impl)
|
||||
{
|
||||
m_impl->Unload();
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
lib.m_impl = nullptr;
|
||||
}
|
||||
|
||||
DynLib::~DynLib()
|
||||
{
|
||||
Unload();
|
||||
}
|
||||
|
||||
String DynLib::GetLastError() const
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
return m_lastError;
|
||||
}
|
||||
|
||||
DynLibFunc DynLib::GetSymbol(const String& symbol) const
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Library not opened");
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->GetSymbol(symbol, &m_lastError);
|
||||
}
|
||||
|
||||
bool DynLib::IsLoaded() const
|
||||
{
|
||||
return m_impl != nullptr;
|
||||
}
|
||||
|
||||
bool DynLib::Load(const String& libraryPath)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
Unload();
|
||||
|
||||
std::unique_ptr<DynLibImpl> impl(new DynLibImpl(this));
|
||||
if (!impl->Load(libraryPath, &m_lastError))
|
||||
{
|
||||
NazaraError("Failed to load library: " + m_lastError);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_impl = impl.release();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DynLib::Unload()
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
if (m_impl)
|
||||
{
|
||||
m_impl->Unload();
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
DynLib& DynLib::operator=(DynLib&& lib)
|
||||
{
|
||||
Unload();
|
||||
|
||||
m_impl = lib.m_impl;
|
||||
m_lastError = std::move(lib.m_lastError);
|
||||
|
||||
lib.m_impl = nullptr;
|
||||
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
|
||||
NzDynLib& NzDynLib::operator=(NzDynLib&& lib)
|
||||
{
|
||||
Unload();
|
||||
|
||||
m_impl = lib.m_impl;
|
||||
m_lastError = std::move(lib.m_lastError);
|
||||
|
||||
lib.m_impl = nullptr;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -16,112 +16,115 @@
|
||||
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
void NzError::Error(nzErrorType type, const NzString& error)
|
||||
namespace Nz
|
||||
{
|
||||
if (type == nzErrorType_AssertFailed || (s_flags & nzErrorFlag_Silent) == 0 || (s_flags & nzErrorFlag_SilentDisabled) != 0)
|
||||
NazaraLog->WriteError(type, error);
|
||||
UInt32 Error::GetFlags()
|
||||
{
|
||||
return s_flags;
|
||||
}
|
||||
|
||||
s_lastError = error;
|
||||
s_lastErrorFile = "";
|
||||
s_lastErrorFunction = "";
|
||||
s_lastErrorLine = 0;
|
||||
String Error::GetLastError(const char** file, unsigned int* line, const char** function)
|
||||
{
|
||||
if (file)
|
||||
*file = s_lastErrorFile;
|
||||
|
||||
#if NAZARA_CORE_EXIT_ON_ASSERT_FAILURE
|
||||
if (type == nzErrorType_AssertFailed)
|
||||
std::abort();
|
||||
#endif
|
||||
if (line)
|
||||
*line = s_lastErrorLine;
|
||||
|
||||
if (type == nzErrorType_AssertFailed || (type != nzErrorType_Warning &&
|
||||
(s_flags & nzErrorFlag_ThrowException) != 0 && (s_flags & nzErrorFlag_ThrowExceptionDisabled) == 0))
|
||||
throw std::runtime_error(error);
|
||||
if (function)
|
||||
*function = s_lastErrorFunction;
|
||||
|
||||
return s_lastError;
|
||||
}
|
||||
|
||||
unsigned int Error::GetLastSystemErrorCode()
|
||||
{
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
return ::GetLastError();
|
||||
#elif defined(NAZARA_PLATFORM_POSIX)
|
||||
return errno;
|
||||
#else
|
||||
#error GetLastSystemErrorCode is not implemented on this platform
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
String Error::GetLastSystemError(unsigned int code)
|
||||
{
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
wchar_t* buffer = nullptr;
|
||||
|
||||
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
nullptr,
|
||||
code,
|
||||
0,
|
||||
reinterpret_cast<LPWSTR>(&buffer),
|
||||
0,
|
||||
nullptr);
|
||||
|
||||
String error(String::Unicode(buffer));
|
||||
LocalFree(buffer);
|
||||
|
||||
error.Trim(); // Pour une raison inconnue, Windows met deux-trois retours à la ligne après le message
|
||||
|
||||
return error;
|
||||
#elif defined(NAZARA_PLATFORM_POSIX)
|
||||
return std::strerror(code);
|
||||
#else
|
||||
#error GetLastSystemError is not implemented on this platform
|
||||
|
||||
return String("GetLastSystemError is not implemented on this platform");
|
||||
#endif
|
||||
}
|
||||
|
||||
void Error::SetFlags(UInt32 flags)
|
||||
{
|
||||
s_flags = flags;
|
||||
}
|
||||
|
||||
void Error::Trigger(ErrorType type, const String& error)
|
||||
{
|
||||
if (type == ErrorType_AssertFailed || (s_flags & ErrorFlag_Silent) == 0 || (s_flags & ErrorFlag_SilentDisabled) != 0)
|
||||
NazaraLog->WriteError(type, error);
|
||||
|
||||
s_lastError = error;
|
||||
s_lastErrorFile = "";
|
||||
s_lastErrorFunction = "";
|
||||
s_lastErrorLine = 0;
|
||||
|
||||
#if NAZARA_CORE_EXIT_ON_ASSERT_FAILURE
|
||||
if (type == ErrorType_AssertFailed)
|
||||
std::abort();
|
||||
#endif
|
||||
|
||||
if (type == ErrorType_AssertFailed || (type != ErrorType_Warning &&
|
||||
(s_flags & ErrorFlag_ThrowException) != 0 && (s_flags & ErrorFlag_ThrowExceptionDisabled) == 0))
|
||||
throw std::runtime_error(error);
|
||||
}
|
||||
|
||||
void Error::Trigger(ErrorType type, const String& error, unsigned int line, const char* file, const char* function)
|
||||
{
|
||||
if (type == ErrorType_AssertFailed || (s_flags & ErrorFlag_Silent) == 0 || (s_flags & ErrorFlag_SilentDisabled) != 0)
|
||||
NazaraLog->WriteError(type, error, line, file, function);
|
||||
|
||||
s_lastError = error;
|
||||
s_lastErrorFile = file;
|
||||
s_lastErrorFunction = function;
|
||||
s_lastErrorLine = line;
|
||||
|
||||
#if NAZARA_CORE_EXIT_ON_ASSERT_FAILURE
|
||||
if (type == ErrorType_AssertFailed)
|
||||
std::abort();
|
||||
#endif
|
||||
|
||||
if (type == ErrorType_AssertFailed || (type != ErrorType_Warning &&
|
||||
(s_flags & ErrorFlag_ThrowException) != 0 && (s_flags & ErrorFlag_ThrowExceptionDisabled) == 0))
|
||||
throw std::runtime_error(error);
|
||||
}
|
||||
|
||||
UInt32 Error::s_flags = ErrorFlag_None;
|
||||
String Error::s_lastError;
|
||||
const char* Error::s_lastErrorFunction = "";
|
||||
const char* Error::s_lastErrorFile = "";
|
||||
unsigned int Error::s_lastErrorLine = 0;
|
||||
}
|
||||
|
||||
void NzError::Error(nzErrorType type, const NzString& error, unsigned int line, const char* file, const char* function)
|
||||
{
|
||||
if (type == nzErrorType_AssertFailed || (s_flags & nzErrorFlag_Silent) == 0 || (s_flags & nzErrorFlag_SilentDisabled) != 0)
|
||||
NazaraLog->WriteError(type, error, line, file, function);
|
||||
|
||||
s_lastError = error;
|
||||
s_lastErrorFile = file;
|
||||
s_lastErrorFunction = function;
|
||||
s_lastErrorLine = line;
|
||||
|
||||
#if NAZARA_CORE_EXIT_ON_ASSERT_FAILURE
|
||||
if (type == nzErrorType_AssertFailed)
|
||||
std::abort();
|
||||
#endif
|
||||
|
||||
if (type == nzErrorType_AssertFailed || (type != nzErrorType_Warning &&
|
||||
(s_flags & nzErrorFlag_ThrowException) != 0 && (s_flags & nzErrorFlag_ThrowExceptionDisabled) == 0))
|
||||
throw std::runtime_error(error);
|
||||
}
|
||||
|
||||
nzUInt32 NzError::GetFlags()
|
||||
{
|
||||
return s_flags;
|
||||
}
|
||||
|
||||
NzString NzError::GetLastError(const char** file, unsigned int* line, const char** function)
|
||||
{
|
||||
if (file)
|
||||
*file = s_lastErrorFile;
|
||||
|
||||
if (line)
|
||||
*line = s_lastErrorLine;
|
||||
|
||||
if (function)
|
||||
*function = s_lastErrorFunction;
|
||||
|
||||
return s_lastError;
|
||||
}
|
||||
|
||||
unsigned int NzError::GetLastSystemErrorCode()
|
||||
{
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
return ::GetLastError();
|
||||
#elif defined(NAZARA_PLATFORM_POSIX)
|
||||
return errno;
|
||||
#else
|
||||
#error GetLastSystemErrorCode is not implemented on this platform
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
NzString NzError::GetLastSystemError(unsigned int code)
|
||||
{
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
wchar_t* buffer = nullptr;
|
||||
|
||||
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
nullptr,
|
||||
code,
|
||||
0,
|
||||
reinterpret_cast<LPWSTR>(&buffer),
|
||||
0,
|
||||
nullptr);
|
||||
|
||||
NzString error(NzString::Unicode(buffer));
|
||||
LocalFree(buffer);
|
||||
|
||||
error.Trim(); // Pour une raison inconnue, Windows met deux-trois retours à la ligne après le message
|
||||
|
||||
return error;
|
||||
#elif defined(NAZARA_PLATFORM_POSIX)
|
||||
return std::strerror(code);
|
||||
#else
|
||||
#error GetLastSystemError is not implemented on this platform
|
||||
|
||||
return NzString("GetLastSystemError is not implemented on this platform");
|
||||
#endif
|
||||
}
|
||||
|
||||
void NzError::SetFlags(nzUInt32 flags)
|
||||
{
|
||||
s_flags = flags;
|
||||
}
|
||||
|
||||
nzUInt32 NzError::s_flags = nzErrorFlag_None;
|
||||
NzString NzError::s_lastError;
|
||||
const char* NzError::s_lastErrorFunction = "";
|
||||
const char* NzError::s_lastErrorFile = "";
|
||||
unsigned int NzError::s_lastErrorLine = 0;
|
||||
|
||||
@@ -6,26 +6,29 @@
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzErrorFlags::NzErrorFlags(nzUInt32 flags, bool replace) :
|
||||
m_previousFlags(NzError::GetFlags())
|
||||
namespace Nz
|
||||
{
|
||||
SetFlags(flags, replace);
|
||||
}
|
||||
ErrorFlags::ErrorFlags(UInt32 flags, bool replace) :
|
||||
m_previousFlags(Error::GetFlags())
|
||||
{
|
||||
SetFlags(flags, replace);
|
||||
}
|
||||
|
||||
NzErrorFlags::~NzErrorFlags()
|
||||
{
|
||||
NzError::SetFlags(m_previousFlags);
|
||||
}
|
||||
ErrorFlags::~ErrorFlags()
|
||||
{
|
||||
Error::SetFlags(m_previousFlags);
|
||||
}
|
||||
|
||||
nzUInt32 NzErrorFlags::GetPreviousFlags() const
|
||||
{
|
||||
return m_previousFlags;
|
||||
}
|
||||
UInt32 ErrorFlags::GetPreviousFlags() const
|
||||
{
|
||||
return m_previousFlags;
|
||||
}
|
||||
|
||||
void NzErrorFlags::SetFlags(nzUInt32 flags, bool replace)
|
||||
{
|
||||
if (!replace)
|
||||
flags |= m_previousFlags;
|
||||
void ErrorFlags::SetFlags(UInt32 flags, bool replace)
|
||||
{
|
||||
if (!replace)
|
||||
flags |= m_previousFlags;
|
||||
|
||||
NzError::SetFlags(flags);
|
||||
Error::SetFlags(flags);
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -14,434 +14,437 @@
|
||||
#include <limits>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
namespace
|
||||
namespace Nz
|
||||
{
|
||||
int ScoreBestAreaFit(int width, int height, const NzRectui& freeRectSize)
|
||||
namespace
|
||||
{
|
||||
return freeRectSize.width * freeRectSize.height - width * height;
|
||||
}
|
||||
|
||||
int ScoreBestLongSideFit(int width, int height, const NzRectui& freeRectSize)
|
||||
{
|
||||
int leftoverHoriz = std::abs(static_cast<int>(freeRectSize.width - width));
|
||||
int leftoverVert = std::abs(static_cast<int>(freeRectSize.height - height));
|
||||
int leftover = std::max(leftoverHoriz, leftoverVert);
|
||||
|
||||
return leftover;
|
||||
}
|
||||
|
||||
int ScoreBestShortSideFit(int width, int height, const NzRectui& freeRectSize)
|
||||
{
|
||||
int leftoverHoriz = std::abs(static_cast<int>(freeRectSize.width - width));
|
||||
int leftoverVert = std::abs(static_cast<int>(freeRectSize.height - height));
|
||||
int leftover = std::min(leftoverHoriz, leftoverVert);
|
||||
|
||||
return leftover;
|
||||
}
|
||||
|
||||
int ScoreWorstAreaFit(int width, int height, const NzRectui& freeRectSize)
|
||||
{
|
||||
return -ScoreBestAreaFit(width, height, freeRectSize);
|
||||
}
|
||||
|
||||
int ScoreWorstLongSideFit(int width, int height, const NzRectui& freeRectSize)
|
||||
{
|
||||
return -ScoreBestLongSideFit(width, height, freeRectSize);
|
||||
}
|
||||
|
||||
int ScoreWorstShortSideFit(int width, int height, const NzRectui& freeRectSize)
|
||||
{
|
||||
return -ScoreBestShortSideFit(width, height, freeRectSize);
|
||||
}
|
||||
}
|
||||
|
||||
NzGuillotineBinPack::NzGuillotineBinPack()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
NzGuillotineBinPack::NzGuillotineBinPack(unsigned int width, unsigned int height)
|
||||
{
|
||||
Reset(width, height);
|
||||
}
|
||||
|
||||
NzGuillotineBinPack::NzGuillotineBinPack(const NzVector2ui& size)
|
||||
{
|
||||
Reset(size);
|
||||
}
|
||||
|
||||
void NzGuillotineBinPack::Clear()
|
||||
{
|
||||
m_freeRectangles.clear();
|
||||
m_freeRectangles.push_back(NzRectui(0, 0, m_width, m_height));
|
||||
|
||||
m_usedArea = 0;
|
||||
}
|
||||
|
||||
void NzGuillotineBinPack::Expand(unsigned int newWidth, unsigned newHeight)
|
||||
{
|
||||
unsigned int oldWidth = m_width;
|
||||
unsigned int oldHeight = m_height;
|
||||
|
||||
m_width = std::max(newWidth, m_width);
|
||||
m_height = std::max(newHeight, m_height);
|
||||
|
||||
if (m_width > oldWidth)
|
||||
m_freeRectangles.push_back(NzRectui(oldWidth, 0, m_width - oldWidth, oldHeight));
|
||||
|
||||
if (m_height > oldHeight)
|
||||
m_freeRectangles.push_back(NzRectui(0, oldHeight, m_width, m_height - oldHeight));
|
||||
|
||||
// On va ensuite fusionner les rectangles tant que possible
|
||||
while (MergeFreeRectangles());
|
||||
}
|
||||
|
||||
void NzGuillotineBinPack::Expand(const NzVector2ui& newSize)
|
||||
{
|
||||
Expand(newSize.x, newSize.y);
|
||||
}
|
||||
|
||||
void NzGuillotineBinPack::FreeRectangle(const NzRectui& rect)
|
||||
{
|
||||
///DOC: Cette méthode ne devrait recevoir que des rectangles calculés par la méthode Insert et peut provoquer de la fragmentation
|
||||
m_freeRectangles.push_back(rect);
|
||||
|
||||
m_usedArea -= rect.width * rect.height;
|
||||
}
|
||||
|
||||
unsigned int NzGuillotineBinPack::GetHeight() const
|
||||
{
|
||||
return m_height;
|
||||
}
|
||||
|
||||
float NzGuillotineBinPack::GetOccupancy() const
|
||||
{
|
||||
return static_cast<float>(m_usedArea)/(m_width*m_height);
|
||||
}
|
||||
|
||||
NzVector2ui NzGuillotineBinPack::GetSize() const
|
||||
{
|
||||
return NzVector2ui(m_width, m_height);
|
||||
}
|
||||
|
||||
unsigned int NzGuillotineBinPack::GetWidth() const
|
||||
{
|
||||
return m_width;
|
||||
}
|
||||
|
||||
bool NzGuillotineBinPack::Insert(NzRectui* rects, unsigned int count, bool merge, FreeRectChoiceHeuristic rectChoice, GuillotineSplitHeuristic splitMethod)
|
||||
{
|
||||
return Insert(rects, nullptr, nullptr, count, merge, rectChoice, splitMethod);
|
||||
}
|
||||
|
||||
bool NzGuillotineBinPack::Insert(NzRectui* rects, bool* flipped, unsigned int count, bool merge, FreeRectChoiceHeuristic rectChoice, GuillotineSplitHeuristic splitMethod)
|
||||
{
|
||||
return Insert(rects, flipped, nullptr, count, merge, rectChoice, splitMethod);
|
||||
}
|
||||
|
||||
bool NzGuillotineBinPack::Insert(NzRectui* rects, bool* flipped, bool* inserted, unsigned int count, bool merge, FreeRectChoiceHeuristic rectChoice, GuillotineSplitHeuristic splitMethod)
|
||||
{
|
||||
std::vector<NzRectui*> remainingRects(count); // La position du rectangle
|
||||
for (unsigned int i = 0; i < count; ++i)
|
||||
remainingRects[i] = &rects[i];
|
||||
|
||||
// Pack rectangles one at a time until we have cleared the rects array of all rectangles.
|
||||
while (!remainingRects.empty())
|
||||
{
|
||||
// Stores the penalty score of the best rectangle placement - bigger=worse, smaller=better.
|
||||
bool bestFlipped;
|
||||
int bestFreeRect;
|
||||
int bestRect;
|
||||
int bestScore = std::numeric_limits<int>::max();
|
||||
|
||||
for (std::size_t i = 0; i < m_freeRectangles.size(); ++i)
|
||||
int ScoreBestAreaFit(int width, int height, const Rectui& freeRectSize)
|
||||
{
|
||||
NzRectui& freeRect = m_freeRectangles[i];
|
||||
return freeRectSize.width * freeRectSize.height - width * height;
|
||||
}
|
||||
|
||||
for (std::size_t j = 0; j < remainingRects.size(); ++j)
|
||||
int ScoreBestLongSideFit(int width, int height, const Rectui& freeRectSize)
|
||||
{
|
||||
int leftoverHoriz = std::abs(static_cast<int>(freeRectSize.width - width));
|
||||
int leftoverVert = std::abs(static_cast<int>(freeRectSize.height - height));
|
||||
int leftover = std::max(leftoverHoriz, leftoverVert);
|
||||
|
||||
return leftover;
|
||||
}
|
||||
|
||||
int ScoreBestShortSideFit(int width, int height, const Rectui& freeRectSize)
|
||||
{
|
||||
int leftoverHoriz = std::abs(static_cast<int>(freeRectSize.width - width));
|
||||
int leftoverVert = std::abs(static_cast<int>(freeRectSize.height - height));
|
||||
int leftover = std::min(leftoverHoriz, leftoverVert);
|
||||
|
||||
return leftover;
|
||||
}
|
||||
|
||||
int ScoreWorstAreaFit(int width, int height, const Rectui& freeRectSize)
|
||||
{
|
||||
return -ScoreBestAreaFit(width, height, freeRectSize);
|
||||
}
|
||||
|
||||
int ScoreWorstLongSideFit(int width, int height, const Rectui& freeRectSize)
|
||||
{
|
||||
return -ScoreBestLongSideFit(width, height, freeRectSize);
|
||||
}
|
||||
|
||||
int ScoreWorstShortSideFit(int width, int height, const Rectui& freeRectSize)
|
||||
{
|
||||
return -ScoreBestShortSideFit(width, height, freeRectSize);
|
||||
}
|
||||
}
|
||||
|
||||
GuillotineBinPack::GuillotineBinPack()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
GuillotineBinPack::GuillotineBinPack(unsigned int width, unsigned int height)
|
||||
{
|
||||
Reset(width, height);
|
||||
}
|
||||
|
||||
GuillotineBinPack::GuillotineBinPack(const Vector2ui& size)
|
||||
{
|
||||
Reset(size);
|
||||
}
|
||||
|
||||
void GuillotineBinPack::Clear()
|
||||
{
|
||||
m_freeRectangles.clear();
|
||||
m_freeRectangles.push_back(Rectui(0, 0, m_width, m_height));
|
||||
|
||||
m_usedArea = 0;
|
||||
}
|
||||
|
||||
void GuillotineBinPack::Expand(unsigned int newWidth, unsigned newHeight)
|
||||
{
|
||||
unsigned int oldWidth = m_width;
|
||||
unsigned int oldHeight = m_height;
|
||||
|
||||
m_width = std::max(newWidth, m_width);
|
||||
m_height = std::max(newHeight, m_height);
|
||||
|
||||
if (m_width > oldWidth)
|
||||
m_freeRectangles.push_back(Rectui(oldWidth, 0, m_width - oldWidth, oldHeight));
|
||||
|
||||
if (m_height > oldHeight)
|
||||
m_freeRectangles.push_back(Rectui(0, oldHeight, m_width, m_height - oldHeight));
|
||||
|
||||
// On va ensuite fusionner les rectangles tant que possible
|
||||
while (MergeFreeRectangles());
|
||||
}
|
||||
|
||||
void GuillotineBinPack::Expand(const Vector2ui& newSize)
|
||||
{
|
||||
Expand(newSize.x, newSize.y);
|
||||
}
|
||||
|
||||
void GuillotineBinPack::FreeRectangle(const Rectui& rect)
|
||||
{
|
||||
///DOC: Cette méthode ne devrait recevoir que des rectangles calculés par la méthode Insert et peut provoquer de la fragmentation
|
||||
m_freeRectangles.push_back(rect);
|
||||
|
||||
m_usedArea -= rect.width * rect.height;
|
||||
}
|
||||
|
||||
unsigned int GuillotineBinPack::GetHeight() const
|
||||
{
|
||||
return m_height;
|
||||
}
|
||||
|
||||
float GuillotineBinPack::GetOccupancy() const
|
||||
{
|
||||
return static_cast<float>(m_usedArea)/(m_width*m_height);
|
||||
}
|
||||
|
||||
Vector2ui GuillotineBinPack::GetSize() const
|
||||
{
|
||||
return Vector2ui(m_width, m_height);
|
||||
}
|
||||
|
||||
unsigned int GuillotineBinPack::GetWidth() const
|
||||
{
|
||||
return m_width;
|
||||
}
|
||||
|
||||
bool GuillotineBinPack::Insert(Rectui* rects, unsigned int count, bool merge, FreeRectChoiceHeuristic rectChoice, GuillotineSplitHeuristic splitMethod)
|
||||
{
|
||||
return Insert(rects, nullptr, nullptr, count, merge, rectChoice, splitMethod);
|
||||
}
|
||||
|
||||
bool GuillotineBinPack::Insert(Rectui* rects, bool* flipped, unsigned int count, bool merge, FreeRectChoiceHeuristic rectChoice, GuillotineSplitHeuristic splitMethod)
|
||||
{
|
||||
return Insert(rects, flipped, nullptr, count, merge, rectChoice, splitMethod);
|
||||
}
|
||||
|
||||
bool GuillotineBinPack::Insert(Rectui* rects, bool* flipped, bool* inserted, unsigned int count, bool merge, FreeRectChoiceHeuristic rectChoice, GuillotineSplitHeuristic splitMethod)
|
||||
{
|
||||
std::vector<Rectui*> remainingRects(count); // La position du rectangle
|
||||
for (unsigned int i = 0; i < count; ++i)
|
||||
remainingRects[i] = &rects[i];
|
||||
|
||||
// Pack rectangles one at a time until we have cleared the rects array of all rectangles.
|
||||
while (!remainingRects.empty())
|
||||
{
|
||||
// Stores the penalty score of the best rectangle placement - bigger=worse, smaller=better.
|
||||
bool bestFlipped;
|
||||
int bestFreeRect;
|
||||
int bestRect;
|
||||
int bestScore = std::numeric_limits<int>::max();
|
||||
|
||||
for (std::size_t i = 0; i < m_freeRectangles.size(); ++i)
|
||||
{
|
||||
NzRectui& rect = *remainingRects[j];
|
||||
Rectui& freeRect = m_freeRectangles[i];
|
||||
|
||||
// If this rectangle is a perfect match, we pick it instantly.
|
||||
if (rect.width == freeRect.width && rect.height == freeRect.height)
|
||||
for (std::size_t j = 0; j < remainingRects.size(); ++j)
|
||||
{
|
||||
bestFreeRect = i;
|
||||
bestRect = j;
|
||||
bestFlipped = false;
|
||||
bestScore = std::numeric_limits<int>::min();
|
||||
i = m_freeRectangles.size(); // Force a jump out of the outer loop as well - we got an instant fit.
|
||||
break;
|
||||
}
|
||||
// If flipping this rectangle is a perfect match, pick that then.
|
||||
else if (rect.height == freeRect.width && rect.width == freeRect.height)
|
||||
{
|
||||
bestFreeRect = i;
|
||||
bestRect = j;
|
||||
bestFlipped = true;
|
||||
bestScore = std::numeric_limits<int>::min();
|
||||
i = m_freeRectangles.size(); // Force a jump out of the outer loop as well - we got an instant fit.
|
||||
break;
|
||||
}
|
||||
// Try if we can fit the rectangle upright.
|
||||
else if (rect.width <= freeRect.width && rect.height <= freeRect.height)
|
||||
{
|
||||
int score = ScoreByHeuristic(rect.width, rect.height, freeRect, rectChoice);
|
||||
if (score < bestScore)
|
||||
Rectui& rect = *remainingRects[j];
|
||||
|
||||
// If this rectangle is a perfect match, we pick it instantly.
|
||||
if (rect.width == freeRect.width && rect.height == freeRect.height)
|
||||
{
|
||||
bestFreeRect = i;
|
||||
bestRect = j;
|
||||
bestFlipped = false;
|
||||
bestScore = score;
|
||||
bestScore = std::numeric_limits<int>::min();
|
||||
i = m_freeRectangles.size(); // Force a jump out of the outer loop as well - we got an instant fit.
|
||||
break;
|
||||
}
|
||||
}
|
||||
// If not, then perhaps flipping sideways will make it fit?
|
||||
else if (rect.height <= freeRect.width && rect.width <= freeRect.height)
|
||||
{
|
||||
int score = ScoreByHeuristic(rect.height, rect.width, freeRect, rectChoice);
|
||||
if (score < bestScore)
|
||||
// If flipping this rectangle is a perfect match, pick that then.
|
||||
else if (rect.height == freeRect.width && rect.width == freeRect.height)
|
||||
{
|
||||
bestFreeRect = i;
|
||||
bestRect = j;
|
||||
bestFlipped = true;
|
||||
bestScore = score;
|
||||
bestScore = std::numeric_limits<int>::min();
|
||||
i = m_freeRectangles.size(); // Force a jump out of the outer loop as well - we got an instant fit.
|
||||
break;
|
||||
}
|
||||
// Try if we can fit the rectangle upright.
|
||||
else if (rect.width <= freeRect.width && rect.height <= freeRect.height)
|
||||
{
|
||||
int score = ScoreByHeuristic(rect.width, rect.height, freeRect, rectChoice);
|
||||
if (score < bestScore)
|
||||
{
|
||||
bestFreeRect = i;
|
||||
bestRect = j;
|
||||
bestFlipped = false;
|
||||
bestScore = score;
|
||||
}
|
||||
}
|
||||
// If not, then perhaps flipping sideways will make it fit?
|
||||
else if (rect.height <= freeRect.width && rect.width <= freeRect.height)
|
||||
{
|
||||
int score = ScoreByHeuristic(rect.height, rect.width, freeRect, rectChoice);
|
||||
if (score < bestScore)
|
||||
{
|
||||
bestFreeRect = i;
|
||||
bestRect = j;
|
||||
bestFlipped = true;
|
||||
bestScore = score;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we didn't manage to find any rectangle to pack, abort.
|
||||
if (bestScore == std::numeric_limits<int>::max())
|
||||
{
|
||||
// Si nous le pouvons, on marque les rectangles n'ayant pas pu être insérés
|
||||
if (inserted)
|
||||
{
|
||||
for (Rectui* rect : remainingRects)
|
||||
{
|
||||
unsigned int position = rect - rects;
|
||||
inserted[position] = false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Otherwise, we're good to go and do the actual packing.
|
||||
unsigned int position = remainingRects[bestRect] - rects;
|
||||
Rectui& rect = *remainingRects[bestRect];
|
||||
rect.x = m_freeRectangles[bestFreeRect].x;
|
||||
rect.y = m_freeRectangles[bestFreeRect].y;
|
||||
|
||||
if (bestFlipped)
|
||||
std::swap(rect.width, rect.height);
|
||||
|
||||
if (flipped)
|
||||
flipped[position] = bestFlipped;
|
||||
|
||||
if (inserted)
|
||||
inserted[position] = true;
|
||||
|
||||
// Remove the free space we lost in the bin.
|
||||
SplitFreeRectByHeuristic(m_freeRectangles[bestFreeRect], rect, splitMethod);
|
||||
m_freeRectangles.erase(m_freeRectangles.begin() + bestFreeRect);
|
||||
|
||||
// Remove the rectangle we just packed from the input list.
|
||||
remainingRects.erase(remainingRects.begin() + bestRect);
|
||||
|
||||
// Perform a Rectangle Merge step if desired.
|
||||
if (merge)
|
||||
MergeFreeRectangles();
|
||||
|
||||
m_usedArea += rect.width * rect.height;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GuillotineBinPack::MergeFreeRectangles()
|
||||
{
|
||||
///DOC: Renvoie true s'il y a eu fusion (et donc si une fusion est encore possible)
|
||||
std::size_t oriSize = m_freeRectangles.size();
|
||||
|
||||
// Do a Theta(n^2) loop to see if any pair of free rectangles could me merged into one.
|
||||
// Note that we miss any opportunities to merge three rectangles into one. (should call this function again to detect that)
|
||||
for (std::size_t i = 0; i < m_freeRectangles.size(); ++i)
|
||||
{
|
||||
Rectui& firstRect = m_freeRectangles[i];
|
||||
|
||||
for (std::size_t j = i+1; j < m_freeRectangles.size(); ++j)
|
||||
{
|
||||
Rectui& secondRect = m_freeRectangles[j];
|
||||
|
||||
if (firstRect.width == secondRect.width && firstRect.x == secondRect.x)
|
||||
{
|
||||
if (firstRect.y == secondRect.y + secondRect.height)
|
||||
{
|
||||
firstRect.y -= secondRect.height;
|
||||
firstRect.height += secondRect.height;
|
||||
m_freeRectangles.erase(m_freeRectangles.begin() + j);
|
||||
--j;
|
||||
}
|
||||
else if (firstRect.y + firstRect.height == secondRect.y)
|
||||
{
|
||||
firstRect.height += secondRect.height;
|
||||
m_freeRectangles.erase(m_freeRectangles.begin() + j);
|
||||
--j;
|
||||
}
|
||||
}
|
||||
else if (firstRect.height == secondRect.height && firstRect.y == secondRect.y)
|
||||
{
|
||||
if (firstRect.x == secondRect.x + secondRect.width)
|
||||
{
|
||||
firstRect.x -= secondRect.width;
|
||||
firstRect.width += secondRect.width;
|
||||
m_freeRectangles.erase(m_freeRectangles.begin() + j);
|
||||
--j;
|
||||
}
|
||||
else if (firstRect.x + firstRect.width == secondRect.x)
|
||||
{
|
||||
firstRect.width += secondRect.width;
|
||||
m_freeRectangles.erase(m_freeRectangles.begin() + j);
|
||||
--j;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we didn't manage to find any rectangle to pack, abort.
|
||||
if (bestScore == std::numeric_limits<int>::max())
|
||||
{
|
||||
// Si nous le pouvons, on marque les rectangles n'ayant pas pu être insérés
|
||||
if (inserted)
|
||||
{
|
||||
for (NzRectui* rect : remainingRects)
|
||||
{
|
||||
unsigned int position = rect - rects;
|
||||
inserted[position] = false;
|
||||
}
|
||||
}
|
||||
return m_freeRectangles.size() < oriSize;
|
||||
}
|
||||
|
||||
return false;
|
||||
void GuillotineBinPack::Reset()
|
||||
{
|
||||
m_height = 0;
|
||||
m_width = 0;
|
||||
|
||||
Clear();
|
||||
}
|
||||
|
||||
void GuillotineBinPack::Reset(unsigned int width, unsigned int height)
|
||||
{
|
||||
m_height = height;
|
||||
m_width = width;
|
||||
|
||||
Clear();
|
||||
}
|
||||
|
||||
void GuillotineBinPack::Reset(const Vector2ui& size)
|
||||
{
|
||||
Reset(size.x, size.y);
|
||||
}
|
||||
|
||||
void GuillotineBinPack::SplitFreeRectAlongAxis(const Rectui& freeRect, const Rectui& placedRect, bool splitHorizontal)
|
||||
{
|
||||
// Form the two new rectangles.
|
||||
Rectui bottom;
|
||||
bottom.x = freeRect.x;
|
||||
bottom.y = freeRect.y + placedRect.height;
|
||||
bottom.height = freeRect.height - placedRect.height;
|
||||
|
||||
Rectui right;
|
||||
right.x = freeRect.x + placedRect.width;
|
||||
right.y = freeRect.y;
|
||||
right.width = freeRect.width - placedRect.width;
|
||||
|
||||
if (splitHorizontal)
|
||||
{
|
||||
bottom.width = freeRect.width;
|
||||
right.height = placedRect.height;
|
||||
}
|
||||
else // Split vertically
|
||||
{
|
||||
bottom.width = placedRect.width;
|
||||
right.height = freeRect.height;
|
||||
}
|
||||
|
||||
// Otherwise, we're good to go and do the actual packing.
|
||||
unsigned int position = remainingRects[bestRect] - rects;
|
||||
NzRectui& rect = *remainingRects[bestRect];
|
||||
rect.x = m_freeRectangles[bestFreeRect].x;
|
||||
rect.y = m_freeRectangles[bestFreeRect].y;
|
||||
// Add the new rectangles into the free rectangle pool if they weren't degenerate.
|
||||
if (bottom.width > 0 && bottom.height > 0)
|
||||
m_freeRectangles.push_back(bottom);
|
||||
|
||||
if (bestFlipped)
|
||||
std::swap(rect.width, rect.height);
|
||||
|
||||
if (flipped)
|
||||
flipped[position] = bestFlipped;
|
||||
|
||||
if (inserted)
|
||||
inserted[position] = true;
|
||||
|
||||
// Remove the free space we lost in the bin.
|
||||
SplitFreeRectByHeuristic(m_freeRectangles[bestFreeRect], rect, splitMethod);
|
||||
m_freeRectangles.erase(m_freeRectangles.begin() + bestFreeRect);
|
||||
|
||||
// Remove the rectangle we just packed from the input list.
|
||||
remainingRects.erase(remainingRects.begin() + bestRect);
|
||||
|
||||
// Perform a Rectangle Merge step if desired.
|
||||
if (merge)
|
||||
MergeFreeRectangles();
|
||||
|
||||
m_usedArea += rect.width * rect.height;
|
||||
if (right.width > 0 && right.height > 0)
|
||||
m_freeRectangles.push_back(right);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzGuillotineBinPack::MergeFreeRectangles()
|
||||
{
|
||||
///DOC: Renvoie true s'il y a eu fusion (et donc si une fusion est encore possible)
|
||||
std::size_t oriSize = m_freeRectangles.size();
|
||||
|
||||
// Do a Theta(n^2) loop to see if any pair of free rectangles could me merged into one.
|
||||
// Note that we miss any opportunities to merge three rectangles into one. (should call this function again to detect that)
|
||||
for (std::size_t i = 0; i < m_freeRectangles.size(); ++i)
|
||||
void GuillotineBinPack::SplitFreeRectByHeuristic(const Rectui& freeRect, const Rectui& placedRect, GuillotineSplitHeuristic method)
|
||||
{
|
||||
NzRectui& firstRect = m_freeRectangles[i];
|
||||
// Compute the lengths of the leftover area.
|
||||
const int w = freeRect.width - placedRect.width;
|
||||
const int h = freeRect.height - placedRect.height;
|
||||
|
||||
for (std::size_t j = i+1; j < m_freeRectangles.size(); ++j)
|
||||
// Placing placedRect into freeRect results in an L-shaped free area, which must be split into
|
||||
// two disjoint rectangles. This can be achieved with by splitting the L-shape using a single line.
|
||||
// We have two choices: horizontal or vertical.
|
||||
|
||||
// Use the given heuristic to decide which choice to make.
|
||||
|
||||
bool splitHorizontal;
|
||||
switch (method)
|
||||
{
|
||||
NzRectui& secondRect = m_freeRectangles[j];
|
||||
case SplitLongerAxis:
|
||||
// Split along the longer total axis.
|
||||
splitHorizontal = (freeRect.width > freeRect.height);
|
||||
break;
|
||||
|
||||
if (firstRect.width == secondRect.width && firstRect.x == secondRect.x)
|
||||
{
|
||||
if (firstRect.y == secondRect.y + secondRect.height)
|
||||
{
|
||||
firstRect.y -= secondRect.height;
|
||||
firstRect.height += secondRect.height;
|
||||
m_freeRectangles.erase(m_freeRectangles.begin() + j);
|
||||
--j;
|
||||
}
|
||||
else if (firstRect.y + firstRect.height == secondRect.y)
|
||||
{
|
||||
firstRect.height += secondRect.height;
|
||||
m_freeRectangles.erase(m_freeRectangles.begin() + j);
|
||||
--j;
|
||||
}
|
||||
}
|
||||
else if (firstRect.height == secondRect.height && firstRect.y == secondRect.y)
|
||||
{
|
||||
if (firstRect.x == secondRect.x + secondRect.width)
|
||||
{
|
||||
firstRect.x -= secondRect.width;
|
||||
firstRect.width += secondRect.width;
|
||||
m_freeRectangles.erase(m_freeRectangles.begin() + j);
|
||||
--j;
|
||||
}
|
||||
else if (firstRect.x + firstRect.width == secondRect.x)
|
||||
{
|
||||
firstRect.width += secondRect.width;
|
||||
m_freeRectangles.erase(m_freeRectangles.begin() + j);
|
||||
--j;
|
||||
}
|
||||
}
|
||||
case SplitLongerLeftoverAxis:
|
||||
// Split along the longer leftover axis.
|
||||
splitHorizontal = (w > h);
|
||||
break;
|
||||
|
||||
case SplitMaximizeArea:
|
||||
// Maximize the smaller area == minimize the larger area.
|
||||
// Tries to make the rectangles more even-sized.
|
||||
splitHorizontal = (placedRect.width * h <= w * placedRect.height);
|
||||
break;
|
||||
|
||||
case SplitMinimizeArea:
|
||||
// Maximize the larger area == minimize the smaller area.
|
||||
// Tries to make the single bigger rectangle.
|
||||
splitHorizontal = (placedRect.width * h > w * placedRect.height);
|
||||
break;
|
||||
|
||||
case SplitShorterAxis:
|
||||
// Split along the shorter total axis.
|
||||
splitHorizontal = (freeRect.width <= freeRect.height);
|
||||
break;
|
||||
|
||||
case SplitShorterLeftoverAxis:
|
||||
// Split along the shorter leftover axis.
|
||||
splitHorizontal = (w <= h);
|
||||
break;
|
||||
|
||||
default:
|
||||
NazaraError("Split heuristic out of enum (0x" + String::Number(method, 16) + ')');
|
||||
splitHorizontal = true;
|
||||
}
|
||||
|
||||
// Perform the actual split.
|
||||
SplitFreeRectAlongAxis(freeRect, placedRect, splitHorizontal);
|
||||
}
|
||||
|
||||
return m_freeRectangles.size() < oriSize;
|
||||
}
|
||||
|
||||
void NzGuillotineBinPack::Reset()
|
||||
{
|
||||
m_height = 0;
|
||||
m_width = 0;
|
||||
|
||||
Clear();
|
||||
}
|
||||
|
||||
void NzGuillotineBinPack::Reset(unsigned int width, unsigned int height)
|
||||
{
|
||||
m_height = height;
|
||||
m_width = width;
|
||||
|
||||
Clear();
|
||||
}
|
||||
|
||||
void NzGuillotineBinPack::Reset(const NzVector2ui& size)
|
||||
{
|
||||
Reset(size.x, size.y);
|
||||
}
|
||||
|
||||
void NzGuillotineBinPack::SplitFreeRectAlongAxis(const NzRectui& freeRect, const NzRectui& placedRect, bool splitHorizontal)
|
||||
{
|
||||
// Form the two new rectangles.
|
||||
NzRectui bottom;
|
||||
bottom.x = freeRect.x;
|
||||
bottom.y = freeRect.y + placedRect.height;
|
||||
bottom.height = freeRect.height - placedRect.height;
|
||||
|
||||
NzRectui right;
|
||||
right.x = freeRect.x + placedRect.width;
|
||||
right.y = freeRect.y;
|
||||
right.width = freeRect.width - placedRect.width;
|
||||
|
||||
if (splitHorizontal)
|
||||
int GuillotineBinPack::ScoreByHeuristic(int width, int height, const Rectui& freeRect, FreeRectChoiceHeuristic rectChoice)
|
||||
{
|
||||
bottom.width = freeRect.width;
|
||||
right.height = placedRect.height;
|
||||
}
|
||||
else // Split vertically
|
||||
{
|
||||
bottom.width = placedRect.width;
|
||||
right.height = freeRect.height;
|
||||
}
|
||||
switch (rectChoice)
|
||||
{
|
||||
case RectBestAreaFit:
|
||||
return ScoreBestAreaFit(width, height, freeRect);
|
||||
|
||||
// Add the new rectangles into the free rectangle pool if they weren't degenerate.
|
||||
if (bottom.width > 0 && bottom.height > 0)
|
||||
m_freeRectangles.push_back(bottom);
|
||||
case RectBestLongSideFit:
|
||||
return ScoreBestLongSideFit(width, height, freeRect);
|
||||
|
||||
if (right.width > 0 && right.height > 0)
|
||||
m_freeRectangles.push_back(right);
|
||||
}
|
||||
|
||||
void NzGuillotineBinPack::SplitFreeRectByHeuristic(const NzRectui& freeRect, const NzRectui& placedRect, GuillotineSplitHeuristic method)
|
||||
{
|
||||
// Compute the lengths of the leftover area.
|
||||
const int w = freeRect.width - placedRect.width;
|
||||
const int h = freeRect.height - placedRect.height;
|
||||
|
||||
// Placing placedRect into freeRect results in an L-shaped free area, which must be split into
|
||||
// two disjoint rectangles. This can be achieved with by splitting the L-shape using a single line.
|
||||
// We have two choices: horizontal or vertical.
|
||||
|
||||
// Use the given heuristic to decide which choice to make.
|
||||
|
||||
bool splitHorizontal;
|
||||
switch (method)
|
||||
{
|
||||
case SplitLongerAxis:
|
||||
// Split along the longer total axis.
|
||||
splitHorizontal = (freeRect.width > freeRect.height);
|
||||
break;
|
||||
|
||||
case SplitLongerLeftoverAxis:
|
||||
// Split along the longer leftover axis.
|
||||
splitHorizontal = (w > h);
|
||||
break;
|
||||
|
||||
case SplitMaximizeArea:
|
||||
// Maximize the smaller area == minimize the larger area.
|
||||
// Tries to make the rectangles more even-sized.
|
||||
splitHorizontal = (placedRect.width * h <= w * placedRect.height);
|
||||
break;
|
||||
|
||||
case SplitMinimizeArea:
|
||||
// Maximize the larger area == minimize the smaller area.
|
||||
// Tries to make the single bigger rectangle.
|
||||
splitHorizontal = (placedRect.width * h > w * placedRect.height);
|
||||
break;
|
||||
|
||||
case SplitShorterAxis:
|
||||
// Split along the shorter total axis.
|
||||
splitHorizontal = (freeRect.width <= freeRect.height);
|
||||
break;
|
||||
|
||||
case SplitShorterLeftoverAxis:
|
||||
// Split along the shorter leftover axis.
|
||||
splitHorizontal = (w <= h);
|
||||
break;
|
||||
|
||||
default:
|
||||
NazaraError("Split heuristic out of enum (0x" + NzString::Number(method, 16) + ')');
|
||||
splitHorizontal = true;
|
||||
}
|
||||
|
||||
// Perform the actual split.
|
||||
SplitFreeRectAlongAxis(freeRect, placedRect, splitHorizontal);
|
||||
}
|
||||
|
||||
int NzGuillotineBinPack::ScoreByHeuristic(int width, int height, const NzRectui& freeRect, FreeRectChoiceHeuristic rectChoice)
|
||||
{
|
||||
switch (rectChoice)
|
||||
{
|
||||
case RectBestAreaFit:
|
||||
return ScoreBestAreaFit(width, height, freeRect);
|
||||
|
||||
case RectBestLongSideFit:
|
||||
return ScoreBestLongSideFit(width, height, freeRect);
|
||||
|
||||
case RectBestShortSideFit:
|
||||
return ScoreBestShortSideFit(width, height, freeRect);
|
||||
|
||||
case RectWorstAreaFit:
|
||||
return ScoreWorstAreaFit(width, height, freeRect);
|
||||
|
||||
case RectWorstLongSideFit:
|
||||
return ScoreWorstLongSideFit(width, height, freeRect);
|
||||
|
||||
case RectWorstShortSideFit:
|
||||
return ScoreWorstShortSideFit(width, height, freeRect);
|
||||
}
|
||||
|
||||
NazaraError("Rect choice heuristic out of enum (0x" + NzString::Number(rectChoice, 16) + ')');
|
||||
return std::numeric_limits<int>::max();
|
||||
case RectBestShortSideFit:
|
||||
return ScoreBestShortSideFit(width, height, freeRect);
|
||||
|
||||
case RectWorstAreaFit:
|
||||
return ScoreWorstAreaFit(width, height, freeRect);
|
||||
|
||||
case RectWorstLongSideFit:
|
||||
return ScoreWorstLongSideFit(width, height, freeRect);
|
||||
|
||||
case RectWorstShortSideFit:
|
||||
return ScoreWorstShortSideFit(width, height, freeRect);
|
||||
}
|
||||
|
||||
NazaraError("Rect choice heuristic out of enum (0x" + String::Number(rectChoice, 16) + ')');
|
||||
return std::numeric_limits<int>::max();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,224 +18,227 @@
|
||||
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
namespace
|
||||
namespace Nz
|
||||
{
|
||||
struct VendorString
|
||||
namespace
|
||||
{
|
||||
char vendor[13]; // +1 pour le \0 automatiquement ajouté par le compilateur
|
||||
nzProcessorVendor vendorEnum;
|
||||
};
|
||||
|
||||
// Exceptionellement, la valeur "unknown" est intégrée
|
||||
const char* vendorNames[] =
|
||||
{
|
||||
"Unknown", // nzProcessorVendor_Unknown
|
||||
"Advanced Micro Devices", // nzProcessorVendor_AMD
|
||||
"Centaur Technology", // nzProcessorVendor_Centaur
|
||||
"Cyrix Corporation", // nzProcessorVendor_Cyrix
|
||||
"Intel Corporation", // nzProcessorVendor_Intel
|
||||
"Kernel-based Virtual Machine", // nzProcessorVendor_KVM
|
||||
"Microsoft Hyper-V", // nzProcessorVendor_HyperV
|
||||
"National Semiconductor", // nzProcessorVendor_NSC
|
||||
"NexGen", // nzProcessorVendor_NexGen
|
||||
"Rise Technology", // nzProcessorVendor_Rise
|
||||
"Silicon Integrated Systems", // nzProcessorVendor_SIS
|
||||
"Transmeta Corporation", // nzProcessorVendor_Transmeta
|
||||
"United Microelectronics Corporation", // nzProcessorVendor_UMC
|
||||
"VIA Technologies", // nzProcessorVendor_VIA
|
||||
"VMware", // nzProcessorVendor_VMware
|
||||
"Vortex86", // nzProcessorVendor_Vortex
|
||||
"Xen" // nzProcessorVendor_XenHVM
|
||||
};
|
||||
|
||||
static_assert(sizeof(vendorNames)/sizeof(const char*) == nzProcessorVendor_Max+2, "Processor vendor name array is incomplete");
|
||||
|
||||
VendorString vendorStrings[] =
|
||||
{
|
||||
// Triés par ordre alphabétique (Majuscules primant sur minuscules)
|
||||
{"AMDisbetter!", nzProcessorVendor_AMD},
|
||||
{"AuthenticAMD", nzProcessorVendor_AMD},
|
||||
{"CentaurHauls", nzProcessorVendor_Centaur},
|
||||
{"CyrixInstead", nzProcessorVendor_Cyrix},
|
||||
{"GenuineIntel", nzProcessorVendor_Intel},
|
||||
{"GenuineTMx86", nzProcessorVendor_Transmeta},
|
||||
{"Geode by NSC", nzProcessorVendor_NSC},
|
||||
{"KVMKVMKVMKVM", nzProcessorVendor_KVM},
|
||||
{"Microsoft Hv", nzProcessorVendor_HyperV},
|
||||
{"NexGenDriven", nzProcessorVendor_NexGen},
|
||||
{"RiseRiseRise", nzProcessorVendor_Rise},
|
||||
{"SiS SiS SiS ", nzProcessorVendor_SIS},
|
||||
{"TransmetaCPU", nzProcessorVendor_Transmeta},
|
||||
{"UMC UMC UMC ", nzProcessorVendor_UMC},
|
||||
{"VIA VIA VIA ", nzProcessorVendor_VIA},
|
||||
{"VMwareVMware", nzProcessorVendor_VMware},
|
||||
{"Vortex86 SoC", nzProcessorVendor_Vortex},
|
||||
{"XenVMMXenVMM", nzProcessorVendor_XenHVM}
|
||||
};
|
||||
|
||||
nzProcessorVendor s_vendorEnum = nzProcessorVendor_Unknown;
|
||||
bool s_capabilities[nzProcessorCap_Max+1] = {false};
|
||||
bool s_initialized = false;
|
||||
|
||||
char s_brandString[48] = "Not initialized";
|
||||
}
|
||||
|
||||
void NzHardwareInfo::Cpuid(nzUInt32 functionId, nzUInt32 subFunctionId, nzUInt32 result[4])
|
||||
{
|
||||
return NzHardwareInfoImpl::Cpuid(functionId, subFunctionId, result);
|
||||
}
|
||||
|
||||
NzString NzHardwareInfo::GetProcessorBrandString()
|
||||
{
|
||||
if (!Initialize())
|
||||
NazaraError("Failed to initialize HardwareInfo");
|
||||
|
||||
return s_brandString;
|
||||
}
|
||||
|
||||
unsigned int NzHardwareInfo::GetProcessorCount()
|
||||
{
|
||||
///DOC: Ne nécessite pas l'initialisation de HardwareInfo pour fonctionner
|
||||
static unsigned int processorCount = std::max(NzHardwareInfoImpl::GetProcessorCount(), 1U);
|
||||
return processorCount;
|
||||
}
|
||||
|
||||
nzProcessorVendor NzHardwareInfo::GetProcessorVendor()
|
||||
{
|
||||
if (!Initialize())
|
||||
NazaraError("Failed to initialize HardwareInfo");
|
||||
|
||||
return s_vendorEnum;
|
||||
}
|
||||
|
||||
NzString NzHardwareInfo::GetProcessorVendorName()
|
||||
{
|
||||
if (!Initialize())
|
||||
NazaraError("Failed to initialize HardwareInfo");
|
||||
|
||||
return vendorNames[s_vendorEnum+1];
|
||||
}
|
||||
|
||||
nzUInt64 NzHardwareInfo::GetTotalMemory()
|
||||
{
|
||||
///DOC: Ne nécessite pas l'initialisation de HardwareInfo pour fonctionner
|
||||
static nzUInt64 totalMemory = NzHardwareInfoImpl::GetTotalMemory();
|
||||
return totalMemory;
|
||||
}
|
||||
|
||||
bool NzHardwareInfo::HasCapability(nzProcessorCap capability)
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (capability > nzProcessorCap_Max)
|
||||
{
|
||||
NazaraError("Capability type out of enum");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return s_capabilities[capability];
|
||||
}
|
||||
|
||||
bool NzHardwareInfo::Initialize()
|
||||
{
|
||||
if (s_initialized)
|
||||
return true;
|
||||
|
||||
if (!NzHardwareInfoImpl::IsCpuidSupported())
|
||||
{
|
||||
NazaraError("Cpuid is not supported");
|
||||
return false;
|
||||
}
|
||||
|
||||
s_initialized = true;
|
||||
|
||||
nzUInt32 registers[4]; // Récupère les quatre registres (EAX, EBX, ECX et EDX)
|
||||
|
||||
// Pour plus de clarté
|
||||
nzUInt32& eax = registers[0];
|
||||
nzUInt32& ebx = registers[1];
|
||||
nzUInt32& ecx = registers[2];
|
||||
nzUInt32& edx = registers[3];
|
||||
|
||||
// Pour commencer, on va récupérer l'identifiant du constructeur ainsi que l'id de fonction maximal supporté par le CPUID
|
||||
NzHardwareInfoImpl::Cpuid(0, 0, registers);
|
||||
|
||||
// Attention à l'ordre : EBX, EDX, ECX
|
||||
nzUInt32 manufacturerId[3] = {ebx, edx, ecx};
|
||||
|
||||
// Identification du concepteur
|
||||
s_vendorEnum = nzProcessorVendor_Unknown;
|
||||
for (const VendorString& vendorString : vendorStrings)
|
||||
{
|
||||
if (std::memcmp(manufacturerId, vendorString.vendor, 12) == 0)
|
||||
struct VendorString
|
||||
{
|
||||
s_vendorEnum = vendorString.vendorEnum;
|
||||
break;
|
||||
char vendor[13]; // +1 pour le \0 automatiquement ajouté par le compilateur
|
||||
ProcessorVendor vendorEnum;
|
||||
};
|
||||
|
||||
// Exceptionellement, la valeur "unknown" est intégrée
|
||||
const char* vendorNames[] =
|
||||
{
|
||||
"Unknown", // ProcessorVendor_Unknown
|
||||
"Advanced Micro Devices", // ProcessorVendor_AMD
|
||||
"Centaur Technology", // ProcessorVendor_Centaur
|
||||
"Cyrix Corporation", // ProcessorVendor_Cyrix
|
||||
"Intel Corporation", // ProcessorVendor_Intel
|
||||
"Kernel-based Virtual Machine", // ProcessorVendor_KVM
|
||||
"Microsoft Hyper-V", // ProcessorVendor_HyperV
|
||||
"National Semiconductor", // ProcessorVendor_NSC
|
||||
"NexGen", // ProcessorVendor_NexGen
|
||||
"Rise Technology", // ProcessorVendor_Rise
|
||||
"Silicon Integrated Systems", // ProcessorVendor_SIS
|
||||
"Transmeta Corporation", // ProcessorVendor_Transmeta
|
||||
"United Microelectronics Corporation", // ProcessorVendor_UMC
|
||||
"VIA Technologies", // ProcessorVendor_VIA
|
||||
"VMware", // ProcessorVendor_VMware
|
||||
"Vortex86", // ProcessorVendor_Vortex
|
||||
"Xen" // ProcessorVendor_XenHVM
|
||||
};
|
||||
|
||||
static_assert(sizeof(vendorNames)/sizeof(const char*) == ProcessorVendor_Max+2, "Processor vendor name array is incomplete");
|
||||
|
||||
VendorString vendorStrings[] =
|
||||
{
|
||||
// Triés par ordre alphabétique (Majuscules primant sur minuscules)
|
||||
{"AMDisbetter!", ProcessorVendor_AMD},
|
||||
{"AuthenticAMD", ProcessorVendor_AMD},
|
||||
{"CentaurHauls", ProcessorVendor_Centaur},
|
||||
{"CyrixInstead", ProcessorVendor_Cyrix},
|
||||
{"GenuineIntel", ProcessorVendor_Intel},
|
||||
{"GenuineTMx86", ProcessorVendor_Transmeta},
|
||||
{"Geode by NSC", ProcessorVendor_NSC},
|
||||
{"KVMKVMKVMKVM", ProcessorVendor_KVM},
|
||||
{"Microsoft Hv", ProcessorVendor_HyperV},
|
||||
{"NexGenDriven", ProcessorVendor_NexGen},
|
||||
{"RiseRiseRise", ProcessorVendor_Rise},
|
||||
{"SiS SiS SiS ", ProcessorVendor_SIS},
|
||||
{"TransmetaCPU", ProcessorVendor_Transmeta},
|
||||
{"UMC UMC UMC ", ProcessorVendor_UMC},
|
||||
{"VIA VIA VIA ", ProcessorVendor_VIA},
|
||||
{"VMwareVMware", ProcessorVendor_VMware},
|
||||
{"Vortex86 SoC", ProcessorVendor_Vortex},
|
||||
{"XenVMMXenVMM", ProcessorVendor_XenHVM}
|
||||
};
|
||||
|
||||
ProcessorVendor s_vendorEnum = ProcessorVendor_Unknown;
|
||||
bool s_capabilities[ProcessorCap_Max+1] = {false};
|
||||
bool s_initialized = false;
|
||||
|
||||
char s_brandString[48] = "Not initialized";
|
||||
}
|
||||
|
||||
void HardwareInfo::Cpuid(UInt32 functionId, UInt32 subFunctionId, UInt32 result[4])
|
||||
{
|
||||
return HardwareInfoImpl::Cpuid(functionId, subFunctionId, result);
|
||||
}
|
||||
|
||||
String HardwareInfo::GetProcessorBrandString()
|
||||
{
|
||||
if (!Initialize())
|
||||
NazaraError("Failed to initialize HardwareInfo");
|
||||
|
||||
return s_brandString;
|
||||
}
|
||||
|
||||
unsigned int HardwareInfo::GetProcessorCount()
|
||||
{
|
||||
///DOC: Ne nécessite pas l'initialisation de HardwareInfo pour fonctionner
|
||||
static unsigned int processorCount = std::max(HardwareInfoImpl::GetProcessorCount(), 1U);
|
||||
return processorCount;
|
||||
}
|
||||
|
||||
ProcessorVendor HardwareInfo::GetProcessorVendor()
|
||||
{
|
||||
if (!Initialize())
|
||||
NazaraError("Failed to initialize HardwareInfo");
|
||||
|
||||
return s_vendorEnum;
|
||||
}
|
||||
|
||||
String HardwareInfo::GetProcessorVendorName()
|
||||
{
|
||||
if (!Initialize())
|
||||
NazaraError("Failed to initialize HardwareInfo");
|
||||
|
||||
return vendorNames[s_vendorEnum+1];
|
||||
}
|
||||
|
||||
UInt64 HardwareInfo::GetTotalMemory()
|
||||
{
|
||||
///DOC: Ne nécessite pas l'initialisation de HardwareInfo pour fonctionner
|
||||
static UInt64 totalMemory = HardwareInfoImpl::GetTotalMemory();
|
||||
return totalMemory;
|
||||
}
|
||||
|
||||
bool HardwareInfo::HasCapability(ProcessorCap capability)
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (capability > ProcessorCap_Max)
|
||||
{
|
||||
NazaraError("Capability type out of enum");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return s_capabilities[capability];
|
||||
}
|
||||
|
||||
if (eax >= 1)
|
||||
bool HardwareInfo::Initialize()
|
||||
{
|
||||
// Récupération de certaines capacités du processeur (ECX et EDX, fonction 1)
|
||||
NzHardwareInfoImpl::Cpuid(1, 0, registers);
|
||||
if (s_initialized)
|
||||
return true;
|
||||
|
||||
s_capabilities[nzProcessorCap_AVX] = (ecx & (1U << 28)) != 0;
|
||||
s_capabilities[nzProcessorCap_FMA3] = (ecx & (1U << 12)) != 0;
|
||||
s_capabilities[nzProcessorCap_MMX] = (edx & (1U << 23)) != 0;
|
||||
s_capabilities[nzProcessorCap_SSE] = (edx & (1U << 25)) != 0;
|
||||
s_capabilities[nzProcessorCap_SSE2] = (edx & (1U << 26)) != 0;
|
||||
s_capabilities[nzProcessorCap_SSE3] = (ecx & (1U << 0)) != 0;
|
||||
s_capabilities[nzProcessorCap_SSSE3] = (ecx & (1U << 9)) != 0;
|
||||
s_capabilities[nzProcessorCap_SSE41] = (ecx & (1U << 19)) != 0;
|
||||
s_capabilities[nzProcessorCap_SSE42] = (ecx & (1U << 20)) != 0;
|
||||
}
|
||||
|
||||
// Récupération de la plus grande fonction étendue supportée (EAX, fonction 0x80000000)
|
||||
NzHardwareInfoImpl::Cpuid(0x80000000, 0, registers);
|
||||
|
||||
nzUInt32 maxSupportedExtendedFunction = eax;
|
||||
if (maxSupportedExtendedFunction >= 0x80000001)
|
||||
{
|
||||
// Récupération des capacités étendues du processeur (ECX et EDX, fonction 0x80000001)
|
||||
NzHardwareInfoImpl::Cpuid(0x80000001, 0, registers);
|
||||
|
||||
s_capabilities[nzProcessorCap_x64] = (edx & (1U << 29)) != 0; // Support du 64bits, indépendant de l'OS
|
||||
s_capabilities[nzProcessorCap_FMA4] = (ecx & (1U << 16)) != 0;
|
||||
s_capabilities[nzProcessorCap_SSE4a] = (ecx & (1U << 6)) != 0;
|
||||
s_capabilities[nzProcessorCap_XOP] = (ecx & (1U << 11)) != 0;
|
||||
|
||||
if (maxSupportedExtendedFunction >= 0x80000004)
|
||||
if (!HardwareInfoImpl::IsCpuidSupported())
|
||||
{
|
||||
// Récupération d'une chaîne de caractère décrivant le processeur (EAX, EBX, ECX et EDX,
|
||||
// fonctions de 0x80000002 à 0x80000004 compris)
|
||||
char* ptr = &s_brandString[0];
|
||||
for (nzUInt32 code = 0x80000002; code <= 0x80000004; ++code)
|
||||
NazaraError("Cpuid is not supported");
|
||||
return false;
|
||||
}
|
||||
|
||||
s_initialized = true;
|
||||
|
||||
UInt32 registers[4]; // Récupère les quatre registres (EAX, EBX, ECX et EDX)
|
||||
|
||||
// Pour plus de clarté
|
||||
UInt32& eax = registers[0];
|
||||
UInt32& ebx = registers[1];
|
||||
UInt32& ecx = registers[2];
|
||||
UInt32& edx = registers[3];
|
||||
|
||||
// Pour commencer, on va récupérer l'identifiant du constructeur ainsi que l'id de fonction maximal supporté par le CPUID
|
||||
HardwareInfoImpl::Cpuid(0, 0, registers);
|
||||
|
||||
// Attention à l'ordre : EBX, EDX, ECX
|
||||
UInt32 manufacturerId[3] = {ebx, edx, ecx};
|
||||
|
||||
// Identification du concepteur
|
||||
s_vendorEnum = ProcessorVendor_Unknown;
|
||||
for (const VendorString& vendorString : vendorStrings)
|
||||
{
|
||||
if (std::memcmp(manufacturerId, vendorString.vendor, 12) == 0)
|
||||
{
|
||||
NzHardwareInfoImpl::Cpuid(code, 0, registers);
|
||||
std::memcpy(ptr, ®isters[0], 4*sizeof(nzUInt32)); // On rajoute les 16 octets à la chaîne
|
||||
|
||||
ptr += 4*sizeof(nzUInt32);
|
||||
s_vendorEnum = vendorString.vendorEnum;
|
||||
break;
|
||||
}
|
||||
|
||||
// Le caractère nul faisant partie de la chaîne retournée par le CPUID, pas besoin de le rajouter
|
||||
}
|
||||
|
||||
if (eax >= 1)
|
||||
{
|
||||
// Récupération de certaines capacités du processeur (ECX et EDX, fonction 1)
|
||||
HardwareInfoImpl::Cpuid(1, 0, registers);
|
||||
|
||||
s_capabilities[ProcessorCap_AVX] = (ecx & (1U << 28)) != 0;
|
||||
s_capabilities[ProcessorCap_FMA3] = (ecx & (1U << 12)) != 0;
|
||||
s_capabilities[ProcessorCap_MMX] = (edx & (1U << 23)) != 0;
|
||||
s_capabilities[ProcessorCap_SSE] = (edx & (1U << 25)) != 0;
|
||||
s_capabilities[ProcessorCap_SSE2] = (edx & (1U << 26)) != 0;
|
||||
s_capabilities[ProcessorCap_SSE3] = (ecx & (1U << 0)) != 0;
|
||||
s_capabilities[ProcessorCap_SSSE3] = (ecx & (1U << 9)) != 0;
|
||||
s_capabilities[ProcessorCap_SSE41] = (ecx & (1U << 19)) != 0;
|
||||
s_capabilities[ProcessorCap_SSE42] = (ecx & (1U << 20)) != 0;
|
||||
}
|
||||
|
||||
// Récupération de la plus grande fonction étendue supportée (EAX, fonction 0x80000000)
|
||||
HardwareInfoImpl::Cpuid(0x80000000, 0, registers);
|
||||
|
||||
UInt32 maxSupportedExtendedFunction = eax;
|
||||
if (maxSupportedExtendedFunction >= 0x80000001)
|
||||
{
|
||||
// Récupération des capacités étendues du processeur (ECX et EDX, fonction 0x80000001)
|
||||
HardwareInfoImpl::Cpuid(0x80000001, 0, registers);
|
||||
|
||||
s_capabilities[ProcessorCap_x64] = (edx & (1U << 29)) != 0; // Support du 64bits, indépendant de l'OS
|
||||
s_capabilities[ProcessorCap_FMA4] = (ecx & (1U << 16)) != 0;
|
||||
s_capabilities[ProcessorCap_SSE4a] = (ecx & (1U << 6)) != 0;
|
||||
s_capabilities[ProcessorCap_XOP] = (ecx & (1U << 11)) != 0;
|
||||
|
||||
if (maxSupportedExtendedFunction >= 0x80000004)
|
||||
{
|
||||
// Récupération d'une chaîne de caractère décrivant le processeur (EAX, EBX, ECX et EDX,
|
||||
// fonctions de 0x80000002 à 0x80000004 compris)
|
||||
char* ptr = &s_brandString[0];
|
||||
for (UInt32 code = 0x80000002; code <= 0x80000004; ++code)
|
||||
{
|
||||
HardwareInfoImpl::Cpuid(code, 0, registers);
|
||||
std::memcpy(ptr, ®isters[0], 4*sizeof(UInt32)); // On rajoute les 16 octets à la chaîne
|
||||
|
||||
ptr += 4*sizeof(UInt32);
|
||||
}
|
||||
|
||||
// Le caractère nul faisant partie de la chaîne retournée par le CPUID, pas besoin de le rajouter
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
bool HardwareInfo::IsCpuidSupported()
|
||||
{
|
||||
return HardwareInfoImpl::IsCpuidSupported();
|
||||
}
|
||||
|
||||
bool NzHardwareInfo::IsCpuidSupported()
|
||||
{
|
||||
return NzHardwareInfoImpl::IsCpuidSupported();
|
||||
}
|
||||
bool HardwareInfo::IsInitialized()
|
||||
{
|
||||
return s_initialized;
|
||||
}
|
||||
|
||||
bool NzHardwareInfo::IsInitialized()
|
||||
{
|
||||
return s_initialized;
|
||||
}
|
||||
|
||||
void NzHardwareInfo::Uninitialize()
|
||||
{
|
||||
// Rien à faire
|
||||
s_initialized = false;
|
||||
void HardwareInfo::Uninitialize()
|
||||
{
|
||||
// Rien à faire
|
||||
s_initialized = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,67 +14,70 @@
|
||||
#include <Nazara/Core/Hash/Whirlpool.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzHash::NzHash(nzHash hash)
|
||||
namespace Nz
|
||||
{
|
||||
switch (hash)
|
||||
Hash::Hash(HashType hash)
|
||||
{
|
||||
case nzHash_Fletcher16:
|
||||
m_impl = new NzHashFletcher16;
|
||||
break;
|
||||
switch (hash)
|
||||
{
|
||||
case HashType_Fletcher16:
|
||||
m_impl = new HashFletcher16;
|
||||
break;
|
||||
|
||||
case nzHash_CRC32:
|
||||
m_impl = new NzHashCRC32;
|
||||
break;
|
||||
case HashType_CRC32:
|
||||
m_impl = new HashCRC32;
|
||||
break;
|
||||
|
||||
case nzHash_MD5:
|
||||
m_impl = new NzHashMD5;
|
||||
break;
|
||||
case HashType_MD5:
|
||||
m_impl = new HashMD5;
|
||||
break;
|
||||
|
||||
case nzHash_SHA1:
|
||||
m_impl = new NzHashSHA1;
|
||||
break;
|
||||
case HashType_SHA1:
|
||||
m_impl = new HashSHA1;
|
||||
break;
|
||||
|
||||
case nzHash_SHA224:
|
||||
m_impl = new NzHashSHA224;
|
||||
break;
|
||||
case HashType_SHA224:
|
||||
m_impl = new HashSHA224;
|
||||
break;
|
||||
|
||||
case nzHash_SHA256:
|
||||
m_impl = new NzHashSHA256;
|
||||
break;
|
||||
case HashType_SHA256:
|
||||
m_impl = new HashSHA256;
|
||||
break;
|
||||
|
||||
case nzHash_SHA384:
|
||||
m_impl = new NzHashSHA384;
|
||||
break;
|
||||
case HashType_SHA384:
|
||||
m_impl = new HashSHA384;
|
||||
break;
|
||||
|
||||
case nzHash_SHA512:
|
||||
m_impl = new NzHashSHA512;
|
||||
break;
|
||||
case HashType_SHA512:
|
||||
m_impl = new HashSHA512;
|
||||
break;
|
||||
|
||||
case nzHash_Whirlpool:
|
||||
m_impl = new NzHashWhirlpool;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
NzHash::NzHash(NzAbstractHash* hashImpl) :
|
||||
m_impl(hashImpl)
|
||||
{
|
||||
}
|
||||
|
||||
NzHash::~NzHash()
|
||||
{
|
||||
delete m_impl;
|
||||
}
|
||||
|
||||
NzHashDigest NzHash::Hash(const NzHashable& hashable)
|
||||
{
|
||||
m_impl->Begin();
|
||||
if (hashable.FillHash(m_impl))
|
||||
return m_impl->End();
|
||||
else // Erreur
|
||||
{
|
||||
m_impl->End();
|
||||
|
||||
return NzHashDigest();
|
||||
case HashType_Whirlpool:
|
||||
m_impl = new HashWhirlpool;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Hash::Hash(AbstractHash* hashImpl) :
|
||||
m_impl(hashImpl)
|
||||
{
|
||||
}
|
||||
|
||||
Hash::~Hash()
|
||||
{
|
||||
delete m_impl;
|
||||
}
|
||||
|
||||
HashDigest Hash::Process(const Hashable& hashable)
|
||||
{
|
||||
m_impl->Begin();
|
||||
if (hashable.FillHash(m_impl))
|
||||
return m_impl->End();
|
||||
else // Erreur
|
||||
{
|
||||
m_impl->End();
|
||||
|
||||
return HashDigest();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,125 +6,128 @@
|
||||
#include <Nazara/Core/Endianness.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
struct NzHashCRC32_state
|
||||
namespace Nz
|
||||
{
|
||||
nzUInt32 crc;
|
||||
const nzUInt32* table;
|
||||
};
|
||||
|
||||
namespace
|
||||
{
|
||||
nzUInt32 crc32_reflect(nzUInt32 ref, unsigned int j)
|
||||
struct HashCRC32_state
|
||||
{
|
||||
nzUInt32 value = 0;
|
||||
|
||||
for (unsigned int i = 1; i <= j; ++i)
|
||||
{
|
||||
if (ref & 1)
|
||||
value |= 1 << (j - i);
|
||||
|
||||
ref >>= 1;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static const nzUInt32 crc32_table[256] = {
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
|
||||
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
|
||||
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
|
||||
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
|
||||
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
|
||||
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
|
||||
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
|
||||
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
|
||||
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
|
||||
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
|
||||
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
|
||||
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
|
||||
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
|
||||
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
|
||||
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
|
||||
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
|
||||
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
|
||||
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
|
||||
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
|
||||
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
|
||||
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
|
||||
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
|
||||
UInt32 crc;
|
||||
const UInt32* table;
|
||||
};
|
||||
}
|
||||
|
||||
NzHashCRC32::NzHashCRC32(nzUInt32 polynomial)
|
||||
{
|
||||
m_state = new NzHashCRC32_state;
|
||||
|
||||
if (polynomial == 0x04c11db7)
|
||||
m_state->table = crc32_table; // Table précalculée (Bien plus rapide)
|
||||
else
|
||||
namespace
|
||||
{
|
||||
nzUInt32* table = new nzUInt32[256];
|
||||
|
||||
for (unsigned int i = 0; i < 256; ++i)
|
||||
UInt32 crc32_reflect(UInt32 ref, unsigned int j)
|
||||
{
|
||||
table[i] = crc32_reflect(i, 8) << 24;
|
||||
for (unsigned int j = 0; j < 8; ++j)
|
||||
table[i] = (table[i] << 1) ^ (table[i] & ((1 << 31) ? polynomial : 0));
|
||||
UInt32 value = 0;
|
||||
|
||||
table[i] = crc32_reflect(table[i], 32);
|
||||
for (unsigned int i = 1; i <= j; ++i)
|
||||
{
|
||||
if (ref & 1)
|
||||
value |= 1 << (j - i);
|
||||
|
||||
ref >>= 1;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
m_state->table = table;
|
||||
static const UInt32 crc32_table[256] = {
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
|
||||
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
|
||||
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
|
||||
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
|
||||
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
|
||||
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
|
||||
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
|
||||
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
|
||||
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
|
||||
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
|
||||
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
|
||||
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
|
||||
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
|
||||
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
|
||||
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
|
||||
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
|
||||
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
|
||||
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
|
||||
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
|
||||
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
|
||||
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
|
||||
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
|
||||
};
|
||||
}
|
||||
|
||||
HashCRC32::HashCRC32(UInt32 polynomial)
|
||||
{
|
||||
m_state = new HashCRC32_state;
|
||||
|
||||
if (polynomial == 0x04c11db7)
|
||||
m_state->table = crc32_table; // Table précalculée (Bien plus rapide)
|
||||
else
|
||||
{
|
||||
UInt32* table = new UInt32[256];
|
||||
|
||||
for (unsigned int i = 0; i < 256; ++i)
|
||||
{
|
||||
table[i] = crc32_reflect(i, 8) << 24;
|
||||
for (unsigned int j = 0; j < 8; ++j)
|
||||
table[i] = (table[i] << 1) ^ (table[i] & ((1 << 31) ? polynomial : 0));
|
||||
|
||||
table[i] = crc32_reflect(table[i], 32);
|
||||
}
|
||||
|
||||
m_state->table = table;
|
||||
}
|
||||
}
|
||||
|
||||
HashCRC32::~HashCRC32()
|
||||
{
|
||||
if (m_state->table != crc32_table)
|
||||
delete[] m_state->table;
|
||||
|
||||
delete m_state;
|
||||
}
|
||||
|
||||
void HashCRC32::Append(const UInt8* data, unsigned int len)
|
||||
{
|
||||
while (len--)
|
||||
m_state->crc = m_state->table[(m_state->crc ^ *data++) & 0xFF] ^ (m_state->crc >> 8);
|
||||
}
|
||||
|
||||
void HashCRC32::Begin()
|
||||
{
|
||||
m_state->crc = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
HashDigest HashCRC32::End()
|
||||
{
|
||||
m_state->crc ^= 0xFFFFFFFF;
|
||||
|
||||
#ifdef NAZARA_LITTLE_ENDIAN
|
||||
SwapBytes(&m_state->crc, sizeof(UInt32));
|
||||
#endif
|
||||
|
||||
return HashDigest(GetHashName(), reinterpret_cast<UInt8*>(&m_state->crc), 4);
|
||||
}
|
||||
|
||||
unsigned int HashCRC32::GetDigestLength()
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
String HashCRC32::GetHashName()
|
||||
{
|
||||
static String hashName = "CRC32";
|
||||
return hashName;
|
||||
}
|
||||
}
|
||||
|
||||
NzHashCRC32::~NzHashCRC32()
|
||||
{
|
||||
if (m_state->table != crc32_table)
|
||||
delete[] m_state->table;
|
||||
|
||||
delete m_state;
|
||||
}
|
||||
|
||||
void NzHashCRC32::Append(const nzUInt8* data, unsigned int len)
|
||||
{
|
||||
while (len--)
|
||||
m_state->crc = m_state->table[(m_state->crc ^ *data++) & 0xFF] ^ (m_state->crc >> 8);
|
||||
}
|
||||
|
||||
void NzHashCRC32::Begin()
|
||||
{
|
||||
m_state->crc = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
NzHashDigest NzHashCRC32::End()
|
||||
{
|
||||
m_state->crc ^= 0xFFFFFFFF;
|
||||
|
||||
#ifdef NAZARA_LITTLE_ENDIAN
|
||||
NzByteSwap(&m_state->crc, sizeof(nzUInt32));
|
||||
#endif
|
||||
|
||||
return NzHashDigest(GetHashName(), reinterpret_cast<nzUInt8*>(&m_state->crc), 4);
|
||||
}
|
||||
|
||||
unsigned int NzHashCRC32::GetDigestLength()
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
NzString NzHashCRC32::GetHashName()
|
||||
{
|
||||
static NzString hashName = "CRC32";
|
||||
return hashName;
|
||||
}
|
||||
|
||||
@@ -6,67 +6,70 @@
|
||||
#include <Nazara/Core/Endianness.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
struct NzHashFletcher16_state
|
||||
namespace Nz
|
||||
{
|
||||
nzUInt16 sum1;
|
||||
nzUInt16 sum2;
|
||||
};
|
||||
|
||||
NzHashFletcher16::NzHashFletcher16()
|
||||
{
|
||||
m_state = new NzHashFletcher16_state;
|
||||
}
|
||||
|
||||
NzHashFletcher16::~NzHashFletcher16()
|
||||
{
|
||||
delete m_state;
|
||||
}
|
||||
|
||||
void NzHashFletcher16::Append(const nzUInt8* data, unsigned int len)
|
||||
{
|
||||
while (len)
|
||||
struct HashFletcher16_state
|
||||
{
|
||||
unsigned int tlen = std::min(len, 21U);
|
||||
len -= tlen;
|
||||
do
|
||||
{
|
||||
m_state->sum1 += *data++;
|
||||
m_state->sum2 += m_state->sum1;
|
||||
}
|
||||
while (--tlen);
|
||||
UInt16 sum1;
|
||||
UInt16 sum2;
|
||||
};
|
||||
|
||||
HashFletcher16::HashFletcher16()
|
||||
{
|
||||
m_state = new HashFletcher16_state;
|
||||
}
|
||||
|
||||
HashFletcher16::~HashFletcher16()
|
||||
{
|
||||
delete m_state;
|
||||
}
|
||||
|
||||
void HashFletcher16::Append(const UInt8* data, unsigned int len)
|
||||
{
|
||||
while (len)
|
||||
{
|
||||
unsigned int tlen = std::min(len, 21U);
|
||||
len -= tlen;
|
||||
do
|
||||
{
|
||||
m_state->sum1 += *data++;
|
||||
m_state->sum2 += m_state->sum1;
|
||||
}
|
||||
while (--tlen);
|
||||
|
||||
m_state->sum1 = (m_state->sum1 & 0xff) + (m_state->sum1 >> 8);
|
||||
m_state->sum2 = (m_state->sum2 & 0xff) + (m_state->sum2 >> 8);
|
||||
}
|
||||
}
|
||||
|
||||
void HashFletcher16::Begin()
|
||||
{
|
||||
m_state->sum1 = 0xff;
|
||||
m_state->sum2 = 0xff;
|
||||
}
|
||||
|
||||
HashDigest HashFletcher16::End()
|
||||
{
|
||||
m_state->sum1 = (m_state->sum1 & 0xff) + (m_state->sum1 >> 8);
|
||||
m_state->sum2 = (m_state->sum2 & 0xff) + (m_state->sum2 >> 8);
|
||||
|
||||
UInt32 fletcher = (m_state->sum2 << 8) | m_state->sum1;
|
||||
|
||||
#ifdef NAZARA_BIG_ENDIAN
|
||||
SwapBytes(&fletcher, sizeof(UInt32));
|
||||
#endif
|
||||
|
||||
return HashDigest(GetHashName(), reinterpret_cast<UInt8*>(&fletcher), 2);
|
||||
}
|
||||
|
||||
unsigned int HashFletcher16::GetDigestLength()
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
String HashFletcher16::GetHashName()
|
||||
{
|
||||
static String hashName = "Fletcher16";
|
||||
return hashName;
|
||||
}
|
||||
}
|
||||
|
||||
void NzHashFletcher16::Begin()
|
||||
{
|
||||
m_state->sum1 = 0xff;
|
||||
m_state->sum2 = 0xff;
|
||||
}
|
||||
|
||||
NzHashDigest NzHashFletcher16::End()
|
||||
{
|
||||
m_state->sum1 = (m_state->sum1 & 0xff) + (m_state->sum1 >> 8);
|
||||
m_state->sum2 = (m_state->sum2 & 0xff) + (m_state->sum2 >> 8);
|
||||
|
||||
nzUInt32 fletcher = (m_state->sum2 << 8) | m_state->sum1;
|
||||
|
||||
#ifdef NAZARA_BIG_ENDIAN
|
||||
NzByteSwap(&fletcher, sizeof(nzUInt32));
|
||||
#endif
|
||||
|
||||
return NzHashDigest(GetHashName(), reinterpret_cast<nzUInt8*>(&fletcher), 2);
|
||||
}
|
||||
|
||||
unsigned int NzHashFletcher16::GetDigestLength()
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
NzString NzHashFletcher16::GetHashName()
|
||||
{
|
||||
static NzString hashName = "Fletcher16";
|
||||
return hashName;
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#include <cstring>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
#define T_MASK (static_cast<nzUInt32>(~0))
|
||||
#define T_MASK (static_cast<UInt32>(~0))
|
||||
#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
|
||||
#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
|
||||
#define T3 0x242070db
|
||||
@@ -97,267 +97,269 @@
|
||||
#define T63 0x2ad7d2bb
|
||||
#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
|
||||
|
||||
struct NzHashMD5_state
|
||||
namespace Nz
|
||||
{
|
||||
nzUInt32 count[2]; /* message length in bits, lsw first */
|
||||
nzUInt32 abcd[4]; /* digest buffer */
|
||||
nzUInt8 buf[64]; /* accumulate block */
|
||||
};
|
||||
|
||||
namespace
|
||||
{
|
||||
void md5_process(NzHashMD5_state* state, const nzUInt8* data)
|
||||
struct HashMD5_state
|
||||
{
|
||||
nzUInt32 a = state->abcd[0];
|
||||
nzUInt32 b = state->abcd[1];
|
||||
nzUInt32 c = state->abcd[2];
|
||||
nzUInt32 d = state->abcd[3];
|
||||
nzUInt32 t;
|
||||
|
||||
#ifdef NAZARA_BIG_ENDIAN
|
||||
/* Define storage only for big-endian CPUs. */
|
||||
nzUInt32 X[16];
|
||||
|
||||
/*
|
||||
* On big-endian machines, we must arrange the bytes in the
|
||||
* right order.
|
||||
*/
|
||||
const nzUInt8* xp = data;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 16; ++i, xp += 4)
|
||||
X[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
|
||||
#else
|
||||
/* Define storage for little-endian or both types of CPUs. */
|
||||
nzUInt32 xbuf[16];
|
||||
const nzUInt32* X;
|
||||
|
||||
/*
|
||||
* On little-endian machines, we can process properly aligned
|
||||
* data without copying it.
|
||||
*/
|
||||
if (!((data - static_cast<const nzUInt8*>(nullptr)) & 3))
|
||||
{
|
||||
/* data are properly aligned */
|
||||
X = reinterpret_cast<const nzUInt32*>(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* not aligned */
|
||||
std::memcpy(xbuf, data, 64);
|
||||
X = xbuf;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
|
||||
|
||||
/* Round 1. */
|
||||
/* Let [abcd k s i] denote the operation
|
||||
a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
|
||||
#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
|
||||
#define SET(a, b, c, d, k, s, Ti)\
|
||||
t = a + F(b,c,d) + X[k] + Ti;\
|
||||
a = ROTATE_LEFT(t, s) + b
|
||||
/* Do the following 16 operations. */
|
||||
SET(a, b, c, d, 0, 7, T1);
|
||||
SET(d, a, b, c, 1, 12, T2);
|
||||
SET(c, d, a, b, 2, 17, T3);
|
||||
SET(b, c, d, a, 3, 22, T4);
|
||||
SET(a, b, c, d, 4, 7, T5);
|
||||
SET(d, a, b, c, 5, 12, T6);
|
||||
SET(c, d, a, b, 6, 17, T7);
|
||||
SET(b, c, d, a, 7, 22, T8);
|
||||
SET(a, b, c, d, 8, 7, T9);
|
||||
SET(d, a, b, c, 9, 12, T10);
|
||||
SET(c, d, a, b, 10, 17, T11);
|
||||
SET(b, c, d, a, 11, 22, T12);
|
||||
SET(a, b, c, d, 12, 7, T13);
|
||||
SET(d, a, b, c, 13, 12, T14);
|
||||
SET(c, d, a, b, 14, 17, T15);
|
||||
SET(b, c, d, a, 15, 22, T16);
|
||||
#undef SET
|
||||
|
||||
/* Round 2. */
|
||||
/* Let [abcd k s i] denote the operation
|
||||
a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
|
||||
#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
|
||||
#define SET(a, b, c, d, k, s, Ti)\
|
||||
t = a + G(b,c,d) + X[k] + Ti;\
|
||||
a = ROTATE_LEFT(t, s) + b
|
||||
/* Do the following 16 operations. */
|
||||
SET(a, b, c, d, 1, 5, T17);
|
||||
SET(d, a, b, c, 6, 9, T18);
|
||||
SET(c, d, a, b, 11, 14, T19);
|
||||
SET(b, c, d, a, 0, 20, T20);
|
||||
SET(a, b, c, d, 5, 5, T21);
|
||||
SET(d, a, b, c, 10, 9, T22);
|
||||
SET(c, d, a, b, 15, 14, T23);
|
||||
SET(b, c, d, a, 4, 20, T24);
|
||||
SET(a, b, c, d, 9, 5, T25);
|
||||
SET(d, a, b, c, 14, 9, T26);
|
||||
SET(c, d, a, b, 3, 14, T27);
|
||||
SET(b, c, d, a, 8, 20, T28);
|
||||
SET(a, b, c, d, 13, 5, T29);
|
||||
SET(d, a, b, c, 2, 9, T30);
|
||||
SET(c, d, a, b, 7, 14, T31);
|
||||
SET(b, c, d, a, 12, 20, T32);
|
||||
#undef SET
|
||||
|
||||
/* Round 3. */
|
||||
/* Let [abcd k s t] denote the operation
|
||||
a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
|
||||
#define H(x, y, z) ((x) ^ (y) ^ (z))
|
||||
#define SET(a, b, c, d, k, s, Ti)\
|
||||
t = a + H(b,c,d) + X[k] + Ti;\
|
||||
a = ROTATE_LEFT(t, s) + b
|
||||
/* Do the following 16 operations. */
|
||||
SET(a, b, c, d, 5, 4, T33);
|
||||
SET(d, a, b, c, 8, 11, T34);
|
||||
SET(c, d, a, b, 11, 16, T35);
|
||||
SET(b, c, d, a, 14, 23, T36);
|
||||
SET(a, b, c, d, 1, 4, T37);
|
||||
SET(d, a, b, c, 4, 11, T38);
|
||||
SET(c, d, a, b, 7, 16, T39);
|
||||
SET(b, c, d, a, 10, 23, T40);
|
||||
SET(a, b, c, d, 13, 4, T41);
|
||||
SET(d, a, b, c, 0, 11, T42);
|
||||
SET(c, d, a, b, 3, 16, T43);
|
||||
SET(b, c, d, a, 6, 23, T44);
|
||||
SET(a, b, c, d, 9, 4, T45);
|
||||
SET(d, a, b, c, 12, 11, T46);
|
||||
SET(c, d, a, b, 15, 16, T47);
|
||||
SET(b, c, d, a, 2, 23, T48);
|
||||
#undef SET
|
||||
|
||||
/* Round 4. */
|
||||
/* Let [abcd k s t] denote the operation
|
||||
a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
|
||||
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
|
||||
#define SET(a, b, c, d, k, s, Ti)\
|
||||
t = a + I(b,c,d) + X[k] + Ti;\
|
||||
a = ROTATE_LEFT(t, s) + b
|
||||
/* Do the following 16 operations. */
|
||||
SET(a, b, c, d, 0, 6, T49);
|
||||
SET(d, a, b, c, 7, 10, T50);
|
||||
SET(c, d, a, b, 14, 15, T51);
|
||||
SET(b, c, d, a, 5, 21, T52);
|
||||
SET(a, b, c, d, 12, 6, T53);
|
||||
SET(d, a, b, c, 3, 10, T54);
|
||||
SET(c, d, a, b, 10, 15, T55);
|
||||
SET(b, c, d, a, 1, 21, T56);
|
||||
SET(a, b, c, d, 8, 6, T57);
|
||||
SET(d, a, b, c, 15, 10, T58);
|
||||
SET(c, d, a, b, 6, 15, T59);
|
||||
SET(b, c, d, a, 13, 21, T60);
|
||||
SET(a, b, c, d, 4, 6, T61);
|
||||
SET(d, a, b, c, 11, 10, T62);
|
||||
SET(c, d, a, b, 2, 15, T63);
|
||||
SET(b, c, d, a, 9, 21, T64);
|
||||
#undef SET
|
||||
|
||||
/* Then perform the following additions. (That is increment each
|
||||
of the four registers by the value it had before this block
|
||||
was started.) */
|
||||
state->abcd[0] += a;
|
||||
state->abcd[1] += b;
|
||||
state->abcd[2] += c;
|
||||
state->abcd[3] += d;
|
||||
}
|
||||
}
|
||||
|
||||
NzHashMD5::NzHashMD5()
|
||||
{
|
||||
m_state = new NzHashMD5_state;
|
||||
}
|
||||
|
||||
NzHashMD5::~NzHashMD5()
|
||||
{
|
||||
delete m_state;
|
||||
}
|
||||
|
||||
void NzHashMD5::Append(const nzUInt8* data, unsigned int len)
|
||||
{
|
||||
const nzUInt8 *p = data;
|
||||
int left = len;
|
||||
int offset = (m_state->count[0] >> 3) & 63;
|
||||
nzUInt32 nbits = len << 3;
|
||||
|
||||
if (len <= 0)
|
||||
return;
|
||||
|
||||
/* Update the message length. */
|
||||
m_state->count[1] += len >> 29;
|
||||
m_state->count[0] += nbits;
|
||||
if (m_state->count[0] < nbits)
|
||||
m_state->count[1]++;
|
||||
|
||||
/* Process an initial partial block. */
|
||||
if (offset)
|
||||
{
|
||||
int copy = (offset + len > 64 ? 64 - offset : len);
|
||||
|
||||
std::memcpy(m_state->buf + offset, p, copy);
|
||||
if (offset + copy < 64)
|
||||
return;
|
||||
|
||||
p += copy;
|
||||
left -= copy;
|
||||
md5_process(m_state, m_state->buf);
|
||||
}
|
||||
|
||||
/* Process full blocks. */
|
||||
for (; left >= 64; p += 64, left -= 64)
|
||||
md5_process(m_state, p);
|
||||
|
||||
/* Process a final partial block. */
|
||||
if (left)
|
||||
std::memcpy(m_state->buf, p, left);
|
||||
}
|
||||
|
||||
void NzHashMD5::Begin()
|
||||
{
|
||||
m_state->count[0] = m_state->count[1] = 0;
|
||||
m_state->abcd[0] = 0x67452301;
|
||||
m_state->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
|
||||
m_state->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
|
||||
m_state->abcd[3] = 0x10325476;
|
||||
}
|
||||
|
||||
NzHashDigest NzHashMD5::End()
|
||||
{
|
||||
static const unsigned char pad[64] = {
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
UInt32 count[2]; /* message length in bits, lsw first */
|
||||
UInt32 abcd[4]; /* digest buffer */
|
||||
UInt8 buf[64]; /* accumulate block */
|
||||
};
|
||||
|
||||
nzUInt8 data[8];
|
||||
int i;
|
||||
namespace
|
||||
{
|
||||
void md5_process(HashMD5_state* state, const UInt8* data)
|
||||
{
|
||||
UInt32 a = state->abcd[0];
|
||||
UInt32 b = state->abcd[1];
|
||||
UInt32 c = state->abcd[2];
|
||||
UInt32 d = state->abcd[3];
|
||||
UInt32 t;
|
||||
|
||||
/* Save the length before padding. */
|
||||
for (i = 0; i < 8; ++i)
|
||||
data[i] = static_cast<nzUInt8>(m_state->count[i >> 2] >> ((i & 3) << 3));
|
||||
/* Pad to 56 bytes mod 64. */
|
||||
Append(pad, ((55 - (m_state->count[0] >> 3)) & 63) + 1);
|
||||
/* Append the length. */
|
||||
Append(data, 8);
|
||||
#ifdef NAZARA_BIG_ENDIAN
|
||||
/* Define storage only for big-endian CPUs. */
|
||||
UInt32 X[16];
|
||||
|
||||
nzUInt8 digest[16];
|
||||
for (i = 0; i < 16; ++i)
|
||||
digest[i] = static_cast<nzUInt8>(m_state->abcd[i >> 2] >> ((i & 3) << 3));
|
||||
/*
|
||||
* On big-endian machines, we must arrange the bytes in the
|
||||
* right order.
|
||||
*/
|
||||
const UInt8* xp = data;
|
||||
int i;
|
||||
|
||||
return NzHashDigest(GetHashName(), &digest[0], 16);
|
||||
for (i = 0; i < 16; ++i, xp += 4)
|
||||
X[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
|
||||
#else
|
||||
/* Define storage for little-endian or both types of CPUs. */
|
||||
UInt32 xbuf[16];
|
||||
const UInt32* X;
|
||||
|
||||
/*
|
||||
* On little-endian machines, we can process properly aligned
|
||||
* data without copying it.
|
||||
*/
|
||||
if (!((data - static_cast<const UInt8*>(nullptr)) & 3))
|
||||
{
|
||||
/* data are properly aligned */
|
||||
X = reinterpret_cast<const UInt32*>(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* not aligned */
|
||||
std::memcpy(xbuf, data, 64);
|
||||
X = xbuf;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
|
||||
|
||||
/* Round 1. */
|
||||
/* Let [abcd k s i] denote the operation
|
||||
a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
|
||||
#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
|
||||
#define SET(a, b, c, d, k, s, Ti)\
|
||||
t = a + F(b,c,d) + X[k] + Ti;\
|
||||
a = ROTATE_LEFT(t, s) + b
|
||||
/* Do the following 16 operations. */
|
||||
SET(a, b, c, d, 0, 7, T1);
|
||||
SET(d, a, b, c, 1, 12, T2);
|
||||
SET(c, d, a, b, 2, 17, T3);
|
||||
SET(b, c, d, a, 3, 22, T4);
|
||||
SET(a, b, c, d, 4, 7, T5);
|
||||
SET(d, a, b, c, 5, 12, T6);
|
||||
SET(c, d, a, b, 6, 17, T7);
|
||||
SET(b, c, d, a, 7, 22, T8);
|
||||
SET(a, b, c, d, 8, 7, T9);
|
||||
SET(d, a, b, c, 9, 12, T10);
|
||||
SET(c, d, a, b, 10, 17, T11);
|
||||
SET(b, c, d, a, 11, 22, T12);
|
||||
SET(a, b, c, d, 12, 7, T13);
|
||||
SET(d, a, b, c, 13, 12, T14);
|
||||
SET(c, d, a, b, 14, 17, T15);
|
||||
SET(b, c, d, a, 15, 22, T16);
|
||||
#undef SET
|
||||
|
||||
/* Round 2. */
|
||||
/* Let [abcd k s i] denote the operation
|
||||
a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
|
||||
#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
|
||||
#define SET(a, b, c, d, k, s, Ti)\
|
||||
t = a + G(b,c,d) + X[k] + Ti;\
|
||||
a = ROTATE_LEFT(t, s) + b
|
||||
/* Do the following 16 operations. */
|
||||
SET(a, b, c, d, 1, 5, T17);
|
||||
SET(d, a, b, c, 6, 9, T18);
|
||||
SET(c, d, a, b, 11, 14, T19);
|
||||
SET(b, c, d, a, 0, 20, T20);
|
||||
SET(a, b, c, d, 5, 5, T21);
|
||||
SET(d, a, b, c, 10, 9, T22);
|
||||
SET(c, d, a, b, 15, 14, T23);
|
||||
SET(b, c, d, a, 4, 20, T24);
|
||||
SET(a, b, c, d, 9, 5, T25);
|
||||
SET(d, a, b, c, 14, 9, T26);
|
||||
SET(c, d, a, b, 3, 14, T27);
|
||||
SET(b, c, d, a, 8, 20, T28);
|
||||
SET(a, b, c, d, 13, 5, T29);
|
||||
SET(d, a, b, c, 2, 9, T30);
|
||||
SET(c, d, a, b, 7, 14, T31);
|
||||
SET(b, c, d, a, 12, 20, T32);
|
||||
#undef SET
|
||||
|
||||
/* Round 3. */
|
||||
/* Let [abcd k s t] denote the operation
|
||||
a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
|
||||
#define H(x, y, z) ((x) ^ (y) ^ (z))
|
||||
#define SET(a, b, c, d, k, s, Ti)\
|
||||
t = a + H(b,c,d) + X[k] + Ti;\
|
||||
a = ROTATE_LEFT(t, s) + b
|
||||
/* Do the following 16 operations. */
|
||||
SET(a, b, c, d, 5, 4, T33);
|
||||
SET(d, a, b, c, 8, 11, T34);
|
||||
SET(c, d, a, b, 11, 16, T35);
|
||||
SET(b, c, d, a, 14, 23, T36);
|
||||
SET(a, b, c, d, 1, 4, T37);
|
||||
SET(d, a, b, c, 4, 11, T38);
|
||||
SET(c, d, a, b, 7, 16, T39);
|
||||
SET(b, c, d, a, 10, 23, T40);
|
||||
SET(a, b, c, d, 13, 4, T41);
|
||||
SET(d, a, b, c, 0, 11, T42);
|
||||
SET(c, d, a, b, 3, 16, T43);
|
||||
SET(b, c, d, a, 6, 23, T44);
|
||||
SET(a, b, c, d, 9, 4, T45);
|
||||
SET(d, a, b, c, 12, 11, T46);
|
||||
SET(c, d, a, b, 15, 16, T47);
|
||||
SET(b, c, d, a, 2, 23, T48);
|
||||
#undef SET
|
||||
|
||||
/* Round 4. */
|
||||
/* Let [abcd k s t] denote the operation
|
||||
a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
|
||||
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
|
||||
#define SET(a, b, c, d, k, s, Ti)\
|
||||
t = a + I(b,c,d) + X[k] + Ti;\
|
||||
a = ROTATE_LEFT(t, s) + b
|
||||
/* Do the following 16 operations. */
|
||||
SET(a, b, c, d, 0, 6, T49);
|
||||
SET(d, a, b, c, 7, 10, T50);
|
||||
SET(c, d, a, b, 14, 15, T51);
|
||||
SET(b, c, d, a, 5, 21, T52);
|
||||
SET(a, b, c, d, 12, 6, T53);
|
||||
SET(d, a, b, c, 3, 10, T54);
|
||||
SET(c, d, a, b, 10, 15, T55);
|
||||
SET(b, c, d, a, 1, 21, T56);
|
||||
SET(a, b, c, d, 8, 6, T57);
|
||||
SET(d, a, b, c, 15, 10, T58);
|
||||
SET(c, d, a, b, 6, 15, T59);
|
||||
SET(b, c, d, a, 13, 21, T60);
|
||||
SET(a, b, c, d, 4, 6, T61);
|
||||
SET(d, a, b, c, 11, 10, T62);
|
||||
SET(c, d, a, b, 2, 15, T63);
|
||||
SET(b, c, d, a, 9, 21, T64);
|
||||
#undef SET
|
||||
|
||||
/* Then perform the following additions. (That is increment each
|
||||
of the four registers by the value it had before this block
|
||||
was started.) */
|
||||
state->abcd[0] += a;
|
||||
state->abcd[1] += b;
|
||||
state->abcd[2] += c;
|
||||
state->abcd[3] += d;
|
||||
}
|
||||
}
|
||||
|
||||
HashMD5::HashMD5()
|
||||
{
|
||||
m_state = new HashMD5_state;
|
||||
}
|
||||
|
||||
HashMD5::~HashMD5()
|
||||
{
|
||||
delete m_state;
|
||||
}
|
||||
|
||||
void HashMD5::Append(const UInt8* data, unsigned int len)
|
||||
{
|
||||
const UInt8 *p = data;
|
||||
int left = len;
|
||||
int offset = (m_state->count[0] >> 3) & 63;
|
||||
UInt32 nbits = len << 3;
|
||||
|
||||
if (len <= 0)
|
||||
return;
|
||||
|
||||
/* Update the message length. */
|
||||
m_state->count[1] += len >> 29;
|
||||
m_state->count[0] += nbits;
|
||||
if (m_state->count[0] < nbits)
|
||||
m_state->count[1]++;
|
||||
|
||||
/* Process an initial partial block. */
|
||||
if (offset)
|
||||
{
|
||||
int copy = (offset + len > 64 ? 64 - offset : len);
|
||||
|
||||
std::memcpy(m_state->buf + offset, p, copy);
|
||||
if (offset + copy < 64)
|
||||
return;
|
||||
|
||||
p += copy;
|
||||
left -= copy;
|
||||
md5_process(m_state, m_state->buf);
|
||||
}
|
||||
|
||||
/* Process full blocks. */
|
||||
for (; left >= 64; p += 64, left -= 64)
|
||||
md5_process(m_state, p);
|
||||
|
||||
/* Process a final partial block. */
|
||||
if (left)
|
||||
std::memcpy(m_state->buf, p, left);
|
||||
}
|
||||
|
||||
void HashMD5::Begin()
|
||||
{
|
||||
m_state->count[0] = m_state->count[1] = 0;
|
||||
m_state->abcd[0] = 0x67452301;
|
||||
m_state->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
|
||||
m_state->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
|
||||
m_state->abcd[3] = 0x10325476;
|
||||
}
|
||||
|
||||
HashDigest HashMD5::End()
|
||||
{
|
||||
static const unsigned char pad[64] = {
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
UInt8 data[8];
|
||||
int i;
|
||||
|
||||
/* Save the length before padding. */
|
||||
for (i = 0; i < 8; ++i)
|
||||
data[i] = static_cast<UInt8>(m_state->count[i >> 2] >> ((i & 3) << 3));
|
||||
/* Pad to 56 bytes mod 64. */
|
||||
Append(pad, ((55 - (m_state->count[0] >> 3)) & 63) + 1);
|
||||
/* Append the length. */
|
||||
Append(data, 8);
|
||||
|
||||
UInt8 digest[16];
|
||||
for (i = 0; i < 16; ++i)
|
||||
digest[i] = static_cast<UInt8>(m_state->abcd[i >> 2] >> ((i & 3) << 3));
|
||||
|
||||
return HashDigest(GetHashName(), &digest[0], 16);
|
||||
}
|
||||
|
||||
unsigned int HashMD5::GetDigestLength()
|
||||
{
|
||||
return 16;
|
||||
}
|
||||
|
||||
String HashMD5::GetHashName()
|
||||
{
|
||||
static String hashName = "MD5";
|
||||
return hashName;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int NzHashMD5::GetDigestLength()
|
||||
{
|
||||
return 16;
|
||||
}
|
||||
|
||||
NzString NzHashMD5::GetHashName()
|
||||
{
|
||||
static NzString hashName = "MD5";
|
||||
return hashName;
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -56,52 +56,55 @@
|
||||
#define SHA512_DIGEST_LENGTH 64
|
||||
#define SHA512_DIGEST_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1)
|
||||
|
||||
union SHA_CTX
|
||||
namespace Nz
|
||||
{
|
||||
/* SHA-1 uses this part of the union: */
|
||||
struct
|
||||
{
|
||||
nzUInt32 state[5];
|
||||
nzUInt64 bitcount;
|
||||
nzUInt8 buffer[64];
|
||||
} s1;
|
||||
union SHA_CTX
|
||||
{
|
||||
/* SHA-1 uses this part of the union: */
|
||||
struct
|
||||
{
|
||||
UInt32 state[5];
|
||||
UInt64 bitcount;
|
||||
UInt8 buffer[64];
|
||||
} s1;
|
||||
|
||||
/* SHA-224 and SHA-256 use this part of the union: */
|
||||
struct
|
||||
{
|
||||
nzUInt32 state[8];
|
||||
nzUInt64 bitcount;
|
||||
nzUInt8 buffer[64];
|
||||
} s256;
|
||||
/* SHA-224 and SHA-256 use this part of the union: */
|
||||
struct
|
||||
{
|
||||
UInt32 state[8];
|
||||
UInt64 bitcount;
|
||||
UInt8 buffer[64];
|
||||
} s256;
|
||||
|
||||
/* SHA-384 and SHA-512 use this part of the union: */
|
||||
struct
|
||||
{
|
||||
nzUInt64 state[8];
|
||||
nzUInt64 bitcount[2];
|
||||
nzUInt8 buffer[128];
|
||||
} s512;
|
||||
};
|
||||
/* SHA-384 and SHA-512 use this part of the union: */
|
||||
struct
|
||||
{
|
||||
UInt64 state[8];
|
||||
UInt64 bitcount[2];
|
||||
UInt8 buffer[128];
|
||||
} s512;
|
||||
};
|
||||
|
||||
void SHA1_Init(SHA_CTX*);
|
||||
void SHA1_Update(SHA_CTX*, const nzUInt8*, std::size_t);
|
||||
void SHA1_End(SHA_CTX*, nzUInt8*);
|
||||
void SHA1_Init(SHA_CTX*);
|
||||
void SHA1_Update(SHA_CTX*, const UInt8*, std::size_t);
|
||||
void SHA1_End(SHA_CTX*, UInt8*);
|
||||
|
||||
void SHA224_Init(SHA_CTX*);
|
||||
void SHA224_Update(SHA_CTX*, const nzUInt8*, std::size_t);
|
||||
void SHA224_End(SHA_CTX*, nzUInt8*);
|
||||
void SHA224_Init(SHA_CTX*);
|
||||
void SHA224_Update(SHA_CTX*, const UInt8*, std::size_t);
|
||||
void SHA224_End(SHA_CTX*, UInt8*);
|
||||
|
||||
void SHA256_Init(SHA_CTX*);
|
||||
void SHA256_Update(SHA_CTX*, const nzUInt8*, std::size_t);
|
||||
void SHA256_End(SHA_CTX*, nzUInt8*);
|
||||
void SHA256_Init(SHA_CTX*);
|
||||
void SHA256_Update(SHA_CTX*, const UInt8*, std::size_t);
|
||||
void SHA256_End(SHA_CTX*, UInt8*);
|
||||
|
||||
void SHA384_Init(SHA_CTX*);
|
||||
void SHA384_Update(SHA_CTX*, const nzUInt8*, std::size_t);
|
||||
void SHA384_End(SHA_CTX*, nzUInt8*);
|
||||
void SHA384_Init(SHA_CTX*);
|
||||
void SHA384_Update(SHA_CTX*, const UInt8*, std::size_t);
|
||||
void SHA384_End(SHA_CTX*, UInt8*);
|
||||
|
||||
void SHA512_Init(SHA_CTX*);
|
||||
void SHA512_Update(SHA_CTX*, const nzUInt8*, std::size_t);
|
||||
void SHA512_End(SHA_CTX*, nzUInt8*);
|
||||
void SHA512_Init(SHA_CTX*);
|
||||
void SHA512_Update(SHA_CTX*, const UInt8*, std::size_t);
|
||||
void SHA512_End(SHA_CTX*, UInt8*);
|
||||
}
|
||||
|
||||
#endif /* NAZARA_HASH_SHA2_INTERNAL_HPP */
|
||||
|
||||
|
||||
@@ -6,42 +6,45 @@
|
||||
#include <Nazara/Core/Hash/SHA/Internal.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzHashSHA1::NzHashSHA1()
|
||||
namespace Nz
|
||||
{
|
||||
m_state = new SHA_CTX;
|
||||
}
|
||||
|
||||
NzHashSHA1::~NzHashSHA1()
|
||||
{
|
||||
delete m_state;
|
||||
}
|
||||
|
||||
void NzHashSHA1::Append(const nzUInt8* data, unsigned int len)
|
||||
{
|
||||
SHA1_Update(m_state, data, len);
|
||||
}
|
||||
|
||||
void NzHashSHA1::Begin()
|
||||
{
|
||||
SHA1_Init(m_state);
|
||||
}
|
||||
|
||||
NzHashDigest NzHashSHA1::End()
|
||||
{
|
||||
nzUInt8 digest[SHA1_DIGEST_LENGTH];
|
||||
|
||||
SHA1_End(m_state, digest);
|
||||
|
||||
return NzHashDigest(GetHashName(), digest, SHA1_DIGEST_LENGTH);
|
||||
}
|
||||
|
||||
unsigned int NzHashSHA1::GetDigestLength()
|
||||
{
|
||||
return SHA1_DIGEST_LENGTH;
|
||||
}
|
||||
|
||||
NzString NzHashSHA1::GetHashName()
|
||||
{
|
||||
static NzString hashName = "SHA1";
|
||||
return hashName;
|
||||
HashSHA1::HashSHA1()
|
||||
{
|
||||
m_state = new SHA_CTX;
|
||||
}
|
||||
|
||||
HashSHA1::~HashSHA1()
|
||||
{
|
||||
delete m_state;
|
||||
}
|
||||
|
||||
void HashSHA1::Append(const UInt8* data, unsigned int len)
|
||||
{
|
||||
SHA1_Update(m_state, data, len);
|
||||
}
|
||||
|
||||
void HashSHA1::Begin()
|
||||
{
|
||||
SHA1_Init(m_state);
|
||||
}
|
||||
|
||||
HashDigest HashSHA1::End()
|
||||
{
|
||||
UInt8 digest[SHA1_DIGEST_LENGTH];
|
||||
|
||||
SHA1_End(m_state, digest);
|
||||
|
||||
return HashDigest(GetHashName(), digest, SHA1_DIGEST_LENGTH);
|
||||
}
|
||||
|
||||
unsigned int HashSHA1::GetDigestLength()
|
||||
{
|
||||
return SHA1_DIGEST_LENGTH;
|
||||
}
|
||||
|
||||
String HashSHA1::GetHashName()
|
||||
{
|
||||
static String hashName = "SHA1";
|
||||
return hashName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,42 +6,45 @@
|
||||
#include <Nazara/Core/Hash/SHA/Internal.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzHashSHA224::NzHashSHA224()
|
||||
namespace Nz
|
||||
{
|
||||
m_state = new SHA_CTX;
|
||||
}
|
||||
|
||||
NzHashSHA224::~NzHashSHA224()
|
||||
{
|
||||
delete m_state;
|
||||
}
|
||||
|
||||
void NzHashSHA224::Append(const nzUInt8* data, unsigned int len)
|
||||
{
|
||||
SHA224_Update(m_state, data, len);
|
||||
}
|
||||
|
||||
void NzHashSHA224::Begin()
|
||||
{
|
||||
SHA224_Init(m_state);
|
||||
}
|
||||
|
||||
NzHashDigest NzHashSHA224::End()
|
||||
{
|
||||
nzUInt8 digest[SHA224_DIGEST_LENGTH];
|
||||
|
||||
SHA224_End(m_state, digest);
|
||||
|
||||
return NzHashDigest(GetHashName(), digest, SHA224_DIGEST_LENGTH);
|
||||
}
|
||||
|
||||
unsigned int NzHashSHA224::GetDigestLength()
|
||||
{
|
||||
return SHA224_DIGEST_LENGTH;
|
||||
}
|
||||
|
||||
NzString NzHashSHA224::GetHashName()
|
||||
{
|
||||
static NzString hashName = "SHA224";
|
||||
return hashName;
|
||||
HashSHA224::HashSHA224()
|
||||
{
|
||||
m_state = new SHA_CTX;
|
||||
}
|
||||
|
||||
HashSHA224::~HashSHA224()
|
||||
{
|
||||
delete m_state;
|
||||
}
|
||||
|
||||
void HashSHA224::Append(const UInt8* data, unsigned int len)
|
||||
{
|
||||
SHA224_Update(m_state, data, len);
|
||||
}
|
||||
|
||||
void HashSHA224::Begin()
|
||||
{
|
||||
SHA224_Init(m_state);
|
||||
}
|
||||
|
||||
HashDigest HashSHA224::End()
|
||||
{
|
||||
UInt8 digest[SHA224_DIGEST_LENGTH];
|
||||
|
||||
SHA224_End(m_state, digest);
|
||||
|
||||
return HashDigest(GetHashName(), digest, SHA224_DIGEST_LENGTH);
|
||||
}
|
||||
|
||||
unsigned int HashSHA224::GetDigestLength()
|
||||
{
|
||||
return SHA224_DIGEST_LENGTH;
|
||||
}
|
||||
|
||||
String HashSHA224::GetHashName()
|
||||
{
|
||||
static String hashName = "SHA224";
|
||||
return hashName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,42 +6,45 @@
|
||||
#include <Nazara/Core/Hash/SHA/Internal.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzHashSHA256::NzHashSHA256()
|
||||
namespace Nz
|
||||
{
|
||||
m_state = new SHA_CTX;
|
||||
}
|
||||
|
||||
NzHashSHA256::~NzHashSHA256()
|
||||
{
|
||||
delete m_state;
|
||||
}
|
||||
|
||||
void NzHashSHA256::Append(const nzUInt8* data, unsigned int len)
|
||||
{
|
||||
SHA256_Update(m_state, data, len);
|
||||
}
|
||||
|
||||
void NzHashSHA256::Begin()
|
||||
{
|
||||
SHA256_Init(m_state);
|
||||
}
|
||||
|
||||
NzHashDigest NzHashSHA256::End()
|
||||
{
|
||||
nzUInt8 digest[SHA256_DIGEST_LENGTH];
|
||||
|
||||
SHA256_End(m_state, digest);
|
||||
|
||||
return NzHashDigest(GetHashName(), digest, SHA256_DIGEST_LENGTH);
|
||||
}
|
||||
|
||||
unsigned int NzHashSHA256::GetDigestLength()
|
||||
{
|
||||
return SHA256_DIGEST_LENGTH;
|
||||
}
|
||||
|
||||
NzString NzHashSHA256::GetHashName()
|
||||
{
|
||||
static NzString hashName = "SHA256";
|
||||
return hashName;
|
||||
HashSHA256::HashSHA256()
|
||||
{
|
||||
m_state = new SHA_CTX;
|
||||
}
|
||||
|
||||
HashSHA256::~HashSHA256()
|
||||
{
|
||||
delete m_state;
|
||||
}
|
||||
|
||||
void HashSHA256::Append(const UInt8* data, unsigned int len)
|
||||
{
|
||||
SHA256_Update(m_state, data, len);
|
||||
}
|
||||
|
||||
void HashSHA256::Begin()
|
||||
{
|
||||
SHA256_Init(m_state);
|
||||
}
|
||||
|
||||
HashDigest HashSHA256::End()
|
||||
{
|
||||
UInt8 digest[SHA256_DIGEST_LENGTH];
|
||||
|
||||
SHA256_End(m_state, digest);
|
||||
|
||||
return HashDigest(GetHashName(), digest, SHA256_DIGEST_LENGTH);
|
||||
}
|
||||
|
||||
unsigned int HashSHA256::GetDigestLength()
|
||||
{
|
||||
return SHA256_DIGEST_LENGTH;
|
||||
}
|
||||
|
||||
String HashSHA256::GetHashName()
|
||||
{
|
||||
static String hashName = "SHA256";
|
||||
return hashName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,42 +6,45 @@
|
||||
#include <Nazara/Core/Hash/SHA/Internal.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzHashSHA384::NzHashSHA384()
|
||||
namespace Nz
|
||||
{
|
||||
m_state = new SHA_CTX;
|
||||
}
|
||||
|
||||
NzHashSHA384::~NzHashSHA384()
|
||||
{
|
||||
delete m_state;
|
||||
}
|
||||
|
||||
void NzHashSHA384::Append(const nzUInt8* data, unsigned int len)
|
||||
{
|
||||
SHA384_Update(m_state, data, len);
|
||||
}
|
||||
|
||||
void NzHashSHA384::Begin()
|
||||
{
|
||||
SHA384_Init(m_state);
|
||||
}
|
||||
|
||||
NzHashDigest NzHashSHA384::End()
|
||||
{
|
||||
nzUInt8 digest[SHA384_DIGEST_LENGTH];
|
||||
|
||||
SHA384_End(m_state, digest);
|
||||
|
||||
return NzHashDigest(GetHashName(), digest, SHA384_DIGEST_LENGTH);
|
||||
}
|
||||
|
||||
unsigned int NzHashSHA384::GetDigestLength()
|
||||
{
|
||||
return SHA384_DIGEST_LENGTH;
|
||||
}
|
||||
|
||||
NzString NzHashSHA384::GetHashName()
|
||||
{
|
||||
static NzString hashName = "SHA384";
|
||||
return hashName;
|
||||
HashSHA384::HashSHA384()
|
||||
{
|
||||
m_state = new SHA_CTX;
|
||||
}
|
||||
|
||||
HashSHA384::~HashSHA384()
|
||||
{
|
||||
delete m_state;
|
||||
}
|
||||
|
||||
void HashSHA384::Append(const UInt8* data, unsigned int len)
|
||||
{
|
||||
SHA384_Update(m_state, data, len);
|
||||
}
|
||||
|
||||
void HashSHA384::Begin()
|
||||
{
|
||||
SHA384_Init(m_state);
|
||||
}
|
||||
|
||||
HashDigest HashSHA384::End()
|
||||
{
|
||||
UInt8 digest[SHA384_DIGEST_LENGTH];
|
||||
|
||||
SHA384_End(m_state, digest);
|
||||
|
||||
return HashDigest(GetHashName(), digest, SHA384_DIGEST_LENGTH);
|
||||
}
|
||||
|
||||
unsigned int HashSHA384::GetDigestLength()
|
||||
{
|
||||
return SHA384_DIGEST_LENGTH;
|
||||
}
|
||||
|
||||
String HashSHA384::GetHashName()
|
||||
{
|
||||
static String hashName = "SHA384";
|
||||
return hashName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,42 +6,45 @@
|
||||
#include <Nazara/Core/Hash/SHA/Internal.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzHashSHA512::NzHashSHA512()
|
||||
namespace Nz
|
||||
{
|
||||
m_state = new SHA_CTX;
|
||||
}
|
||||
|
||||
NzHashSHA512::~NzHashSHA512()
|
||||
{
|
||||
delete m_state;
|
||||
}
|
||||
|
||||
void NzHashSHA512::Append(const nzUInt8* data, unsigned int len)
|
||||
{
|
||||
SHA512_Update(m_state, data, len);
|
||||
}
|
||||
|
||||
void NzHashSHA512::Begin()
|
||||
{
|
||||
SHA512_Init(m_state);
|
||||
}
|
||||
|
||||
NzHashDigest NzHashSHA512::End()
|
||||
{
|
||||
nzUInt8 digest[SHA512_DIGEST_LENGTH];
|
||||
|
||||
SHA512_End(m_state, digest);
|
||||
|
||||
return NzHashDigest(GetHashName(), digest, SHA512_DIGEST_LENGTH);
|
||||
}
|
||||
|
||||
unsigned int NzHashSHA512::GetDigestLength()
|
||||
{
|
||||
return SHA512_DIGEST_LENGTH;
|
||||
}
|
||||
|
||||
NzString NzHashSHA512::GetHashName()
|
||||
{
|
||||
static NzString hashName = "SHA512";
|
||||
return hashName;
|
||||
HashSHA512::HashSHA512()
|
||||
{
|
||||
m_state = new SHA_CTX;
|
||||
}
|
||||
|
||||
HashSHA512::~HashSHA512()
|
||||
{
|
||||
delete m_state;
|
||||
}
|
||||
|
||||
void HashSHA512::Append(const UInt8* data, unsigned int len)
|
||||
{
|
||||
SHA512_Update(m_state, data, len);
|
||||
}
|
||||
|
||||
void HashSHA512::Begin()
|
||||
{
|
||||
SHA512_Init(m_state);
|
||||
}
|
||||
|
||||
HashDigest HashSHA512::End()
|
||||
{
|
||||
UInt8 digest[SHA512_DIGEST_LENGTH];
|
||||
|
||||
SHA512_End(m_state, digest);
|
||||
|
||||
return HashDigest(GetHashName(), digest, SHA512_DIGEST_LENGTH);
|
||||
}
|
||||
|
||||
unsigned int HashSHA512::GetDigestLength()
|
||||
{
|
||||
return SHA512_DIGEST_LENGTH;
|
||||
}
|
||||
|
||||
String HashSHA512::GetHashName()
|
||||
{
|
||||
static String hashName = "SHA512";
|
||||
return hashName;
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -10,181 +10,184 @@
|
||||
#include <cstring>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzHashDigest::NzHashDigest() :
|
||||
m_digest(nullptr),
|
||||
m_digestLength(0)
|
||||
namespace Nz
|
||||
{
|
||||
}
|
||||
|
||||
NzHashDigest::NzHashDigest(const NzString& hashName, const nzUInt8* digest, unsigned int length) :
|
||||
m_hashName(hashName),
|
||||
m_digestLength(length)
|
||||
{
|
||||
if (m_digestLength > 0)
|
||||
HashDigest::HashDigest() :
|
||||
m_digest(nullptr),
|
||||
m_digestLength(0)
|
||||
{
|
||||
m_digest = new nzUInt8[length];
|
||||
std::memcpy(m_digest, digest, length);
|
||||
}
|
||||
else
|
||||
m_digest = nullptr;
|
||||
}
|
||||
|
||||
NzHashDigest::NzHashDigest(const NzHashDigest& rhs) :
|
||||
m_hashName(rhs.m_hashName),
|
||||
m_digestLength(rhs.m_digestLength)
|
||||
{
|
||||
if (m_digestLength > 0)
|
||||
HashDigest::HashDigest(const String& hashName, const UInt8* digest, unsigned int length) :
|
||||
m_hashName(hashName),
|
||||
m_digestLength(length)
|
||||
{
|
||||
m_digest = new nzUInt8[m_digestLength];
|
||||
std::memcpy(m_digest, rhs.m_digest, m_digestLength);
|
||||
if (m_digestLength > 0)
|
||||
{
|
||||
m_digest = new UInt8[length];
|
||||
std::memcpy(m_digest, digest, length);
|
||||
}
|
||||
else
|
||||
m_digest = nullptr;
|
||||
}
|
||||
else
|
||||
m_digest = nullptr;
|
||||
}
|
||||
|
||||
NzHashDigest::NzHashDigest(NzHashDigest&& rhs) noexcept :
|
||||
m_hashName(std::move(rhs.m_hashName)),
|
||||
m_digest(rhs.m_digest),
|
||||
m_digestLength(rhs.m_digestLength)
|
||||
{
|
||||
rhs.m_digest = nullptr;
|
||||
rhs.m_digestLength = 0;
|
||||
}
|
||||
|
||||
NzHashDigest::~NzHashDigest()
|
||||
{
|
||||
delete[] m_digest;
|
||||
}
|
||||
|
||||
bool NzHashDigest::IsValid() const
|
||||
{
|
||||
return m_digestLength > 0;
|
||||
}
|
||||
|
||||
const nzUInt8* NzHashDigest::GetDigest() const
|
||||
{
|
||||
return m_digest;
|
||||
}
|
||||
|
||||
unsigned int NzHashDigest::GetDigestLength() const
|
||||
{
|
||||
return m_digestLength;
|
||||
}
|
||||
|
||||
NzString NzHashDigest::GetHashName() const
|
||||
{
|
||||
return m_hashName;
|
||||
}
|
||||
|
||||
NzString NzHashDigest::ToHex() const
|
||||
{
|
||||
if (m_digestLength == 0)
|
||||
return NzString();
|
||||
|
||||
unsigned int length = m_digestLength*2;
|
||||
|
||||
NzString hexOutput(length);
|
||||
for (unsigned int i = 0; i < m_digestLength; ++i)
|
||||
std::sprintf(&hexOutput[i*2], "%02x", m_digest[i]);
|
||||
|
||||
return hexOutput;
|
||||
}
|
||||
|
||||
nzUInt8 NzHashDigest::operator[](unsigned int pos) const
|
||||
{
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (pos >= m_digestLength)
|
||||
HashDigest::HashDigest(const HashDigest& rhs) :
|
||||
m_hashName(rhs.m_hashName),
|
||||
m_digestLength(rhs.m_digestLength)
|
||||
{
|
||||
NazaraError("Position out of range");
|
||||
return 0;
|
||||
if (m_digestLength > 0)
|
||||
{
|
||||
m_digest = new UInt8[m_digestLength];
|
||||
std::memcpy(m_digest, rhs.m_digest, m_digestLength);
|
||||
}
|
||||
else
|
||||
m_digest = nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_digest[pos];
|
||||
}
|
||||
HashDigest::HashDigest(HashDigest&& rhs) noexcept :
|
||||
m_hashName(std::move(rhs.m_hashName)),
|
||||
m_digest(rhs.m_digest),
|
||||
m_digestLength(rhs.m_digestLength)
|
||||
{
|
||||
rhs.m_digest = nullptr;
|
||||
rhs.m_digestLength = 0;
|
||||
}
|
||||
|
||||
HashDigest::~HashDigest()
|
||||
{
|
||||
delete[] m_digest;
|
||||
}
|
||||
|
||||
bool HashDigest::IsValid() const
|
||||
{
|
||||
return m_digestLength > 0;
|
||||
}
|
||||
|
||||
const UInt8* HashDigest::GetDigest() const
|
||||
{
|
||||
return m_digest;
|
||||
}
|
||||
|
||||
unsigned int HashDigest::GetDigestLength() const
|
||||
{
|
||||
return m_digestLength;
|
||||
}
|
||||
|
||||
String HashDigest::GetHashName() const
|
||||
{
|
||||
return m_hashName;
|
||||
}
|
||||
|
||||
String HashDigest::ToHex() const
|
||||
{
|
||||
if (m_digestLength == 0)
|
||||
return String();
|
||||
|
||||
unsigned int length = m_digestLength*2;
|
||||
|
||||
String hexOutput(length);
|
||||
for (unsigned int i = 0; i < m_digestLength; ++i)
|
||||
std::sprintf(&hexOutput[i*2], "%02x", m_digest[i]);
|
||||
|
||||
return hexOutput;
|
||||
}
|
||||
|
||||
UInt8 HashDigest::operator[](unsigned int pos) const
|
||||
{
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (pos >= m_digestLength)
|
||||
{
|
||||
NazaraError("Position out of range");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_digest[pos];
|
||||
}
|
||||
|
||||
HashDigest& HashDigest::operator=(const HashDigest& rhs)
|
||||
{
|
||||
if (this == &rhs)
|
||||
return *this;
|
||||
|
||||
m_hashName = rhs.m_hashName;
|
||||
|
||||
m_digestLength = rhs.m_digestLength;
|
||||
if (m_digestLength > 0)
|
||||
{
|
||||
m_digest = new UInt8[m_digestLength];
|
||||
std::memcpy(m_digest, rhs.m_digest, m_digestLength);
|
||||
}
|
||||
else
|
||||
m_digest = nullptr;
|
||||
|
||||
NzHashDigest& NzHashDigest::operator=(const NzHashDigest& rhs)
|
||||
{
|
||||
if (this == &rhs)
|
||||
return *this;
|
||||
|
||||
m_hashName = rhs.m_hashName;
|
||||
|
||||
m_digestLength = rhs.m_digestLength;
|
||||
if (m_digestLength > 0)
|
||||
{
|
||||
m_digest = new nzUInt8[m_digestLength];
|
||||
std::memcpy(m_digest, rhs.m_digest, m_digestLength);
|
||||
}
|
||||
else
|
||||
m_digest = nullptr;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzHashDigest& NzHashDigest::operator=(NzHashDigest&& rhs) noexcept
|
||||
{
|
||||
std::swap(m_hashName, rhs.m_hashName);
|
||||
std::swap(m_digest, rhs.m_digest);
|
||||
std::swap(m_digestLength, rhs.m_digestLength);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool NzHashDigest::operator==(const NzHashDigest& rhs) const
|
||||
{
|
||||
if (m_digest == nullptr || rhs.m_digest == nullptr)
|
||||
return m_digest == rhs.m_digest;
|
||||
|
||||
if (m_digestLength != rhs.m_digestLength)
|
||||
return false;
|
||||
|
||||
return m_hashName == rhs.m_hashName && std::memcmp(m_digest, rhs.m_digest, m_digestLength) == 0;
|
||||
}
|
||||
|
||||
bool NzHashDigest::operator!=(const NzHashDigest& rhs) const
|
||||
{
|
||||
return !operator==(rhs);
|
||||
}
|
||||
|
||||
bool NzHashDigest::operator<(const NzHashDigest& rhs) const
|
||||
{
|
||||
if (rhs.m_digest == nullptr)
|
||||
return false;
|
||||
|
||||
if (m_digest == nullptr)
|
||||
return true;
|
||||
|
||||
int cmp = NzString::Compare(m_hashName, rhs.m_hashName);
|
||||
if (cmp == 0)
|
||||
HashDigest& HashDigest::operator=(HashDigest&& rhs) noexcept
|
||||
{
|
||||
cmp = std::memcmp(m_digest, rhs.m_digest, std::min(m_digestLength, rhs.m_digestLength));
|
||||
std::swap(m_hashName, rhs.m_hashName);
|
||||
std::swap(m_digest, rhs.m_digest);
|
||||
std::swap(m_digestLength, rhs.m_digestLength);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool HashDigest::operator==(const HashDigest& rhs) const
|
||||
{
|
||||
if (m_digest == nullptr || rhs.m_digest == nullptr)
|
||||
return m_digest == rhs.m_digest;
|
||||
|
||||
if (m_digestLength != rhs.m_digestLength)
|
||||
return false;
|
||||
|
||||
return m_hashName == rhs.m_hashName && std::memcmp(m_digest, rhs.m_digest, m_digestLength) == 0;
|
||||
}
|
||||
|
||||
bool HashDigest::operator!=(const HashDigest& rhs) const
|
||||
{
|
||||
return !operator==(rhs);
|
||||
}
|
||||
|
||||
bool HashDigest::operator<(const HashDigest& rhs) const
|
||||
{
|
||||
if (rhs.m_digest == nullptr)
|
||||
return false;
|
||||
|
||||
if (m_digest == nullptr)
|
||||
return true;
|
||||
|
||||
int cmp = String::Compare(m_hashName, rhs.m_hashName);
|
||||
if (cmp == 0)
|
||||
return m_digestLength < rhs.m_digestLength;
|
||||
{
|
||||
cmp = std::memcmp(m_digest, rhs.m_digest, std::min(m_digestLength, rhs.m_digestLength));
|
||||
|
||||
if (cmp == 0)
|
||||
return m_digestLength < rhs.m_digestLength;
|
||||
else
|
||||
return cmp < 0;
|
||||
}
|
||||
else
|
||||
return cmp < 0;
|
||||
}
|
||||
else
|
||||
return cmp < 0;
|
||||
|
||||
bool HashDigest::operator<=(const HashDigest& rhs) const
|
||||
{
|
||||
return !rhs.operator<(*this);
|
||||
}
|
||||
|
||||
bool HashDigest::operator>(const HashDigest& rhs) const
|
||||
{
|
||||
return rhs.operator<(*this);
|
||||
}
|
||||
|
||||
bool HashDigest::operator>=(const HashDigest& rhs) const
|
||||
{
|
||||
return !operator<(rhs);
|
||||
}
|
||||
}
|
||||
|
||||
bool NzHashDigest::operator<=(const NzHashDigest& rhs) const
|
||||
{
|
||||
return !rhs.operator<(*this);
|
||||
}
|
||||
|
||||
bool NzHashDigest::operator>(const NzHashDigest& rhs) const
|
||||
{
|
||||
return rhs.operator<(*this);
|
||||
}
|
||||
|
||||
bool NzHashDigest::operator>=(const NzHashDigest& rhs) const
|
||||
{
|
||||
return !operator<(rhs);
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const NzHashDigest& hashstring)
|
||||
std::ostream& operator<<(std::ostream& out, const Nz::HashDigest& hashstring)
|
||||
{
|
||||
out << hashstring.ToHex();
|
||||
return out;
|
||||
|
||||
@@ -6,16 +6,19 @@
|
||||
#include <Nazara/Core/Hash.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzHashable::~NzHashable() = default;
|
||||
|
||||
NzHashDigest NzHashable::GetHash(nzHash hash) const
|
||||
namespace Nz
|
||||
{
|
||||
NzHash h(hash);
|
||||
return h.Hash(*this);
|
||||
}
|
||||
Hashable::~Hashable() = default;
|
||||
|
||||
NzHashDigest NzHashable::GetHash(NzAbstractHash* impl) const
|
||||
{
|
||||
NzHash h(impl);
|
||||
return h.Hash(*this);
|
||||
HashDigest Hashable::GetHash(HashType hash) const
|
||||
{
|
||||
Hash h(hash);
|
||||
return h.Process(*this);
|
||||
}
|
||||
|
||||
HashDigest Hashable::GetHash(AbstractHash* impl) const
|
||||
{
|
||||
Hash h(impl);
|
||||
return h.Process(*this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,61 +8,64 @@
|
||||
#include <cstring>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzInputStream::~NzInputStream() = default;
|
||||
|
||||
NzString NzInputStream::ReadLine(unsigned int lineSize)
|
||||
namespace Nz
|
||||
{
|
||||
NzString line;
|
||||
if (lineSize == 0) // Taille maximale indéterminée
|
||||
InputStream::~InputStream() = default;
|
||||
|
||||
String InputStream::ReadLine(unsigned int lineSize)
|
||||
{
|
||||
const unsigned int bufferSize = 64;
|
||||
|
||||
char buffer[bufferSize+1];
|
||||
buffer[bufferSize] = '\0';
|
||||
|
||||
unsigned int readSize;
|
||||
do
|
||||
String line;
|
||||
if (lineSize == 0) // Taille maximale indéterminée
|
||||
{
|
||||
readSize = Read(buffer, bufferSize);
|
||||
const unsigned int bufferSize = 64;
|
||||
|
||||
const char* ptr = std::strchr(buffer, '\n');
|
||||
if (ptr)
|
||||
char buffer[bufferSize+1];
|
||||
buffer[bufferSize] = '\0';
|
||||
|
||||
unsigned int readSize;
|
||||
do
|
||||
{
|
||||
unsigned int pos = ptr-buffer;
|
||||
readSize = Read(buffer, bufferSize);
|
||||
|
||||
if (m_streamOptions & nzStreamOption_Text && pos > 0 && buffer[pos-1] == '\r')
|
||||
line.Append(buffer, pos-1);
|
||||
const char* ptr = std::strchr(buffer, '\n');
|
||||
if (ptr)
|
||||
{
|
||||
unsigned int pos = ptr-buffer;
|
||||
|
||||
if (m_streamOptions & StreamOption_Text && pos > 0 && buffer[pos-1] == '\r')
|
||||
line.Append(buffer, pos-1);
|
||||
else
|
||||
line.Append(buffer, pos);
|
||||
|
||||
if (!SetCursorPos(GetCursorPos() - readSize + pos + 1))
|
||||
NazaraWarning("Failed to reset cursos pos");
|
||||
|
||||
break;
|
||||
}
|
||||
else
|
||||
line.Append(buffer, pos);
|
||||
line.Append(buffer, readSize);
|
||||
}
|
||||
while (readSize == bufferSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
line.Set(lineSize, '\0');
|
||||
unsigned int readSize = Read(&line[0], lineSize);
|
||||
unsigned int pos = line.Find('\n');
|
||||
if (pos <= readSize) // Faux uniquement si le caractère n'est pas présent (npos étant le plus grand entier)
|
||||
{
|
||||
if (m_streamOptions & StreamOption_Text && pos > 0 && line[pos-1] == '\r')
|
||||
line.Resize(pos);
|
||||
else
|
||||
line.Resize(pos+1);
|
||||
|
||||
if (!SetCursorPos(GetCursorPos() - readSize + pos + 1))
|
||||
NazaraWarning("Failed to reset cursos pos");
|
||||
|
||||
break;
|
||||
}
|
||||
else
|
||||
line.Append(buffer, readSize);
|
||||
line.Resize(readSize);
|
||||
}
|
||||
while (readSize == bufferSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
line.Set(lineSize, '\0');
|
||||
unsigned int readSize = Read(&line[0], lineSize);
|
||||
unsigned int pos = line.Find('\n');
|
||||
if (pos <= readSize) // Faux uniquement si le caractère n'est pas présent (npos étant le plus grand entier)
|
||||
{
|
||||
if (m_streamOptions & nzStreamOption_Text && pos > 0 && line[pos-1] == '\r')
|
||||
line.Resize(pos);
|
||||
else
|
||||
line.Resize(pos+1);
|
||||
|
||||
if (!SetCursorPos(GetCursorPos() - readSize + pos + 1))
|
||||
NazaraWarning("Failed to reset cursos pos");
|
||||
}
|
||||
else
|
||||
line.Resize(readSize);
|
||||
return line;
|
||||
}
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
@@ -6,13 +6,16 @@
|
||||
#include <Nazara/Core/Mutex.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzLockGuard::NzLockGuard(NzMutex& mutex) :
|
||||
m_mutex(mutex)
|
||||
namespace Nz
|
||||
{
|
||||
m_mutex.Lock();
|
||||
}
|
||||
LockGuard::LockGuard(Mutex& mutex) :
|
||||
m_mutex(mutex)
|
||||
{
|
||||
m_mutex.Lock();
|
||||
}
|
||||
|
||||
NzLockGuard::~NzLockGuard()
|
||||
{
|
||||
m_mutex.Unlock();
|
||||
LockGuard::~LockGuard()
|
||||
{
|
||||
m_mutex.Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,142 +21,145 @@
|
||||
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
namespace
|
||||
namespace Nz
|
||||
{
|
||||
const char* errorType[] = {
|
||||
"Assert failed: ", // nzErrorType_AssertFailed
|
||||
"Internal error: ", // nzErrorType_Internal
|
||||
"Error: ", // nzErrorType_Normal
|
||||
"Warning: " // nzErrorType_Warning
|
||||
};
|
||||
namespace
|
||||
{
|
||||
const char* errorType[] = {
|
||||
"Assert failed: ", // ErrorType_AssertFailed
|
||||
"Internal error: ", // ErrorType_Internal
|
||||
"Error: ", // ErrorType_Normal
|
||||
"Warning: " // ErrorType_Warning
|
||||
};
|
||||
|
||||
static_assert(sizeof(errorType)/sizeof(const char*) == nzErrorType_Max+1, "Error type array is incomplete");
|
||||
}
|
||||
static_assert(sizeof(errorType)/sizeof(const char*) == ErrorType_Max+1, "Error type array is incomplete");
|
||||
}
|
||||
|
||||
NzLog::NzLog() :
|
||||
m_filePath("NazaraLog.log"),
|
||||
m_file(nullptr),
|
||||
m_append(false),
|
||||
m_enabled(true),
|
||||
m_writeTime(true)
|
||||
{
|
||||
}
|
||||
Log::Log() :
|
||||
m_filePath("NazaraLog.log"),
|
||||
m_file(nullptr),
|
||||
m_append(false),
|
||||
m_enabled(true),
|
||||
m_writeTime(true)
|
||||
{
|
||||
}
|
||||
|
||||
NzLog::~NzLog()
|
||||
{
|
||||
delete m_file;
|
||||
}
|
||||
|
||||
void NzLog::Enable(bool enable)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
if (m_enabled == enable)
|
||||
return;
|
||||
|
||||
m_enabled = enable;
|
||||
if (!m_enabled && m_file)
|
||||
Log::~Log()
|
||||
{
|
||||
delete m_file;
|
||||
m_file = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void NzLog::EnableAppend(bool enable)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
m_append = enable;
|
||||
if (!m_append && m_file)
|
||||
void Log::Enable(bool enable)
|
||||
{
|
||||
m_file->Delete();
|
||||
m_file = nullptr;
|
||||
}
|
||||
}
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
void NzLog::EnableDateTime(bool enable)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
if (m_enabled == enable)
|
||||
return;
|
||||
|
||||
m_writeTime = enable;
|
||||
}
|
||||
|
||||
NzString NzLog::GetFile() const
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
if (m_file)
|
||||
return m_file->GetPath();
|
||||
else
|
||||
return NzString();
|
||||
}
|
||||
|
||||
bool NzLog::IsEnabled() const
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
return m_enabled;
|
||||
}
|
||||
|
||||
void NzLog::SetFile(const NzString& filePath)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
m_filePath = filePath;
|
||||
if (m_file)
|
||||
m_file->SetFile(filePath);
|
||||
}
|
||||
|
||||
void NzLog::Write(const NzString& string)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
if (m_enabled)
|
||||
{
|
||||
if (!m_file)
|
||||
m_file = new NzFile(m_filePath, nzOpenMode_Text | nzOpenMode_WriteOnly | ((m_append) ? nzOpenMode_Append : nzOpenMode_Truncate));
|
||||
|
||||
NzString line;
|
||||
|
||||
if (m_writeTime)
|
||||
m_enabled = enable;
|
||||
if (!m_enabled && m_file)
|
||||
{
|
||||
line.Reserve(23 + string.GetSize() + 1);
|
||||
line.Set(23, '\0'); // Buffer non-initialisé
|
||||
|
||||
time_t currentTime = std::time(nullptr);
|
||||
std::strftime(&line[0], 24, "%d/%m/%Y - %H:%M:%S: ", std::localtime(¤tTime));
|
||||
delete m_file;
|
||||
m_file = nullptr;
|
||||
}
|
||||
else
|
||||
line.Reserve(string.GetSize() + 1);
|
||||
|
||||
line += string;
|
||||
line += '\n';
|
||||
|
||||
if (m_file->IsOpen())
|
||||
m_file->Write(line);
|
||||
|
||||
#if NAZARA_CORE_DUPLICATE_LOG_TO_COUT
|
||||
std::fputs(line.GetConstBuffer(), stdout);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void NzLog::WriteError(nzErrorType type, const NzString& error)
|
||||
{
|
||||
NzStringStream stream;
|
||||
stream << errorType[type] << error;
|
||||
Write(stream);
|
||||
}
|
||||
void Log::EnableAppend(bool enable)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
void NzLog::WriteError(nzErrorType type, const NzString& error, unsigned int line, const NzString& file, const NzString& func)
|
||||
{
|
||||
NzStringStream stream;
|
||||
stream << errorType[type] << error << " (" << file << ':' << line << ": " << func << ')';
|
||||
Write(stream);
|
||||
}
|
||||
m_append = enable;
|
||||
if (!m_append && m_file)
|
||||
{
|
||||
m_file->Delete();
|
||||
m_file = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
NzLog* NzLog::Instance()
|
||||
{
|
||||
static NzLog log;
|
||||
return &log;
|
||||
void Log::EnableDateTime(bool enable)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
m_writeTime = enable;
|
||||
}
|
||||
|
||||
String Log::GetFile() const
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
if (m_file)
|
||||
return m_file->GetPath();
|
||||
else
|
||||
return String();
|
||||
}
|
||||
|
||||
bool Log::IsEnabled() const
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
return m_enabled;
|
||||
}
|
||||
|
||||
void Log::SetFile(const String& filePath)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
m_filePath = filePath;
|
||||
if (m_file)
|
||||
m_file->SetFile(filePath);
|
||||
}
|
||||
|
||||
void Log::Write(const String& string)
|
||||
{
|
||||
NazaraLock(m_mutex)
|
||||
|
||||
if (m_enabled)
|
||||
{
|
||||
if (!m_file)
|
||||
m_file = new File(m_filePath, OpenMode_Text | OpenMode_WriteOnly | ((m_append) ? OpenMode_Append : OpenMode_Truncate));
|
||||
|
||||
String line;
|
||||
|
||||
if (m_writeTime)
|
||||
{
|
||||
line.Reserve(23 + string.GetSize() + 1);
|
||||
line.Set(23, '\0'); // Buffer non-initialisé
|
||||
|
||||
time_t currentTime = std::time(nullptr);
|
||||
std::strftime(&line[0], 24, "%d/%m/%Y - %H:%M:%S: ", std::localtime(¤tTime));
|
||||
}
|
||||
else
|
||||
line.Reserve(string.GetSize() + 1);
|
||||
|
||||
line += string;
|
||||
line += '\n';
|
||||
|
||||
if (m_file->IsOpen())
|
||||
m_file->Write(line);
|
||||
|
||||
#if NAZARA_CORE_DUPLICATE_LOG_TO_COUT
|
||||
std::fputs(line.GetConstBuffer(), stdout);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void Log::WriteError(ErrorType type, const String& error)
|
||||
{
|
||||
StringStream stream;
|
||||
stream << errorType[type] << error;
|
||||
Write(stream);
|
||||
}
|
||||
|
||||
void Log::WriteError(ErrorType type, const String& error, unsigned int line, const String& file, const String& func)
|
||||
{
|
||||
StringStream stream;
|
||||
stream << errorType[type] << error << " (" << file << ':' << line << ": " << func << ')';
|
||||
Write(stream);
|
||||
}
|
||||
|
||||
Log* Log::Instance()
|
||||
{
|
||||
static Log log;
|
||||
return &log;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,320 +17,323 @@
|
||||
|
||||
// Le seul fichier n'ayant pas à inclure Debug.hpp
|
||||
|
||||
namespace
|
||||
namespace Nz
|
||||
{
|
||||
constexpr unsigned int s_allocatedId = 0xDEADB33FUL;
|
||||
constexpr unsigned int s_freedId = 0x4B1DUL;
|
||||
|
||||
struct Block
|
||||
namespace
|
||||
{
|
||||
std::size_t size;
|
||||
const char* file;
|
||||
Block* prev;
|
||||
Block* next;
|
||||
bool array;
|
||||
unsigned int line;
|
||||
unsigned int magic;
|
||||
};
|
||||
constexpr unsigned int s_allocatedId = 0xDEADB33FUL;
|
||||
constexpr unsigned int s_freedId = 0x4B1DUL;
|
||||
|
||||
bool s_allocationFilling = true;
|
||||
bool s_allocationLogging = false;
|
||||
bool s_initialized = false;
|
||||
const char* s_logFileName = "NazaraMemory.log";
|
||||
thread_local const char* s_nextFreeFile = "(Internal error)";
|
||||
thread_local unsigned int s_nextFreeLine = 0;
|
||||
|
||||
Block s_list =
|
||||
{
|
||||
0,
|
||||
nullptr,
|
||||
&s_list,
|
||||
&s_list,
|
||||
false,
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
unsigned int s_allocationCount = 0;
|
||||
unsigned int s_allocatedBlock = 0;
|
||||
std::size_t s_allocatedSize = 0;
|
||||
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
CRITICAL_SECTION s_mutex;
|
||||
#elif defined(NAZARA_PLATFORM_POSIX)
|
||||
pthread_mutex_t s_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
#endif
|
||||
}
|
||||
|
||||
NzMemoryManager::NzMemoryManager()
|
||||
{
|
||||
}
|
||||
|
||||
NzMemoryManager::~NzMemoryManager()
|
||||
{
|
||||
Uninitialize();
|
||||
}
|
||||
|
||||
void* NzMemoryManager::Allocate(std::size_t size, bool multi, const char* file, unsigned int line)
|
||||
{
|
||||
if (!s_initialized)
|
||||
Initialize();
|
||||
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
EnterCriticalSection(&s_mutex);
|
||||
#elif defined(NAZARA_PLATFORM_POSIX)
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
#endif
|
||||
|
||||
Block* ptr = reinterpret_cast<Block*>(std::malloc(size+sizeof(Block)));
|
||||
if (!ptr)
|
||||
{
|
||||
char timeStr[23];
|
||||
TimeInfo(timeStr);
|
||||
|
||||
FILE* log = std::fopen(s_logFileName, "a");
|
||||
|
||||
if (file)
|
||||
std::fprintf(log, "%s Failed to allocate %zu bytes at %s:%u\n", timeStr, size, file, line);
|
||||
else
|
||||
std::fprintf(log, "%s Failed to allocate %zu bytes at unknown position\n", timeStr, size);
|
||||
|
||||
std::fclose(log);
|
||||
|
||||
throw std::bad_alloc();
|
||||
return nullptr; // Ça me rassure d'avoir un return, aussi inutile soit-il
|
||||
}
|
||||
|
||||
ptr->array = multi;
|
||||
ptr->file = file;
|
||||
ptr->line = line;
|
||||
ptr->size = size;
|
||||
ptr->magic = s_allocatedId;
|
||||
|
||||
ptr->prev = s_list.prev;
|
||||
ptr->next = &s_list;
|
||||
s_list.prev->next = ptr;
|
||||
s_list.prev = ptr;
|
||||
|
||||
s_allocatedBlock++;
|
||||
s_allocatedSize += size;
|
||||
s_allocationCount++;
|
||||
|
||||
if (s_allocationFilling)
|
||||
{
|
||||
nzUInt8* data = reinterpret_cast<nzUInt8*>(ptr) + sizeof(Block);
|
||||
std::memset(data, 0xFF, size);
|
||||
}
|
||||
|
||||
if (s_allocationLogging)
|
||||
{
|
||||
char timeStr[23];
|
||||
TimeInfo(timeStr);
|
||||
|
||||
FILE* log = std::fopen(s_logFileName, "a");
|
||||
|
||||
if (file)
|
||||
std::fprintf(log, "%s Allocated %zu bytes at %s:%u\n", timeStr, size, file, line);
|
||||
else
|
||||
std::fprintf(log, "%s Allocated %zu bytes at unknown position\n", timeStr, size);
|
||||
|
||||
std::fclose(log);
|
||||
}
|
||||
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
LeaveCriticalSection(&s_mutex);
|
||||
#elif defined(NAZARA_PLATFORM_POSIX)
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
#endif
|
||||
|
||||
return reinterpret_cast<nzUInt8*>(ptr) + sizeof(Block);
|
||||
}
|
||||
|
||||
void NzMemoryManager::EnableAllocationFilling(bool allocationFilling)
|
||||
{
|
||||
s_allocationFilling = allocationFilling;
|
||||
}
|
||||
|
||||
void NzMemoryManager::EnableAllocationLogging(bool logAllocations)
|
||||
{
|
||||
s_allocationLogging = logAllocations;
|
||||
}
|
||||
|
||||
void NzMemoryManager::Free(void* pointer, bool multi)
|
||||
{
|
||||
if (!pointer)
|
||||
return;
|
||||
|
||||
Block* ptr = reinterpret_cast<Block*>(reinterpret_cast<nzUInt8*>(pointer) - sizeof(Block));
|
||||
if (ptr->magic != s_allocatedId)
|
||||
{
|
||||
char timeStr[23];
|
||||
TimeInfo(timeStr);
|
||||
|
||||
FILE* log = std::fopen(s_logFileName, "a");
|
||||
|
||||
const char* error = (ptr->magic == s_freedId) ? "double-delete" : "possible delete of dangling pointer";
|
||||
if (s_nextFreeFile)
|
||||
std::fprintf(log, "%s Warning: %s at %s:%u\n", timeStr, error, s_nextFreeFile, s_nextFreeLine);
|
||||
else
|
||||
std::fprintf(log, "%s Warning: %s at unknown position\n", timeStr, error);
|
||||
|
||||
std::fclose(log);
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
EnterCriticalSection(&s_mutex);
|
||||
#elif defined(NAZARA_PLATFORM_POSIX)
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
#endif
|
||||
|
||||
if (ptr->array != multi)
|
||||
{
|
||||
char timeStr[23];
|
||||
TimeInfo(timeStr);
|
||||
|
||||
FILE* log = std::fopen(s_logFileName, "a");
|
||||
|
||||
const char* error = (multi) ? "delete[] after new" : "delete after new[]";
|
||||
if (s_nextFreeFile)
|
||||
std::fprintf(log, "%s Warning: %s at %s:%u\n", timeStr, error, s_nextFreeFile, s_nextFreeLine);
|
||||
else
|
||||
std::fprintf(log, "%s Warning: %s at unknown position\n", timeStr, error);
|
||||
|
||||
std::fclose(log);
|
||||
}
|
||||
|
||||
ptr->magic = s_freedId;
|
||||
ptr->prev->next = ptr->next;
|
||||
ptr->next->prev = ptr->prev;
|
||||
|
||||
s_allocatedBlock--;
|
||||
s_allocatedSize -= ptr->size;
|
||||
|
||||
if (s_allocationFilling)
|
||||
{
|
||||
nzUInt8* data = reinterpret_cast<nzUInt8*>(ptr) + sizeof(Block);
|
||||
std::memset(data, 0xFF, ptr->size);
|
||||
}
|
||||
|
||||
std::free(ptr);
|
||||
|
||||
s_nextFreeFile = nullptr;
|
||||
s_nextFreeLine = 0;
|
||||
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
LeaveCriticalSection(&s_mutex);
|
||||
#elif defined(NAZARA_PLATFORM_POSIX)
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned int NzMemoryManager::GetAllocatedBlockCount()
|
||||
{
|
||||
return s_allocatedBlock;
|
||||
}
|
||||
|
||||
std::size_t NzMemoryManager::GetAllocatedSize()
|
||||
{
|
||||
return s_allocatedSize;
|
||||
}
|
||||
|
||||
unsigned int NzMemoryManager::GetAllocationCount()
|
||||
{
|
||||
return s_allocationCount;
|
||||
}
|
||||
|
||||
bool NzMemoryManager::IsAllocationFillingEnabled()
|
||||
{
|
||||
return s_allocationFilling;
|
||||
}
|
||||
|
||||
bool NzMemoryManager::IsAllocationLoggingEnabled()
|
||||
{
|
||||
return s_allocationLogging;
|
||||
}
|
||||
|
||||
void NzMemoryManager::NextFree(const char* file, unsigned int line)
|
||||
{
|
||||
s_nextFreeFile = file;
|
||||
s_nextFreeLine = line;
|
||||
}
|
||||
|
||||
void NzMemoryManager::Initialize()
|
||||
{
|
||||
char timeStr[23];
|
||||
TimeInfo(timeStr);
|
||||
|
||||
FILE* file = std::fopen(s_logFileName, "w");
|
||||
std::fprintf(file, "%s ==============================\n", timeStr);
|
||||
std::fprintf(file, "%s Nazara Memory Leak Tracker \n", timeStr);
|
||||
std::fprintf(file, "%s ==============================\n", timeStr);
|
||||
std::fclose(file);
|
||||
|
||||
if (std::atexit(Uninitialize) != 0)
|
||||
{
|
||||
static NzMemoryManager manager;
|
||||
}
|
||||
|
||||
#ifdef NAZARA_PLATFORM_WINDOWS
|
||||
InitializeCriticalSection(&s_mutex);
|
||||
//#elif defined(NAZARA_PLATFORM_POSIX) is already done in the namespace
|
||||
#endif
|
||||
|
||||
s_initialized = true;
|
||||
}
|
||||
|
||||
void NzMemoryManager::TimeInfo(char buffer[23])
|
||||
{
|
||||
time_t currentTime = std::time(nullptr);
|
||||
std::strftime(buffer, 23, "%d/%m/%Y - %H:%M:%S:", std::localtime(¤tTime));
|
||||
}
|
||||
|
||||
void NzMemoryManager::Uninitialize()
|
||||
{
|
||||
#ifdef NAZARA_PLATFORM_WINDOWS
|
||||
DeleteCriticalSection(&s_mutex);
|
||||
#elif defined(NAZARA_PLATFORM_POSIX)
|
||||
pthread_mutex_destroy(&s_mutex);
|
||||
#endif
|
||||
|
||||
FILE* log = std::fopen(s_logFileName, "a");
|
||||
|
||||
char timeStr[23];
|
||||
TimeInfo(timeStr);
|
||||
|
||||
std::fprintf(log, "%s Application finished, checking leaks...\n", timeStr);
|
||||
|
||||
if (s_allocatedBlock == 0)
|
||||
{
|
||||
std::fprintf(log, "%s ==============================\n", timeStr);
|
||||
std::fprintf(log, "%s No leak detected \n", timeStr);
|
||||
std::fprintf(log, "%s ==============================", timeStr);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::fprintf(log, "%s ==============================\n", timeStr);
|
||||
std::fprintf(log, "%s Leaks have been detected \n", timeStr);
|
||||
std::fprintf(log, "%s ==============================\n\n", timeStr);
|
||||
std::fputs("Leak list:\n", log);
|
||||
|
||||
Block* ptr = s_list.next;
|
||||
while (ptr != &s_list)
|
||||
struct Block
|
||||
{
|
||||
if (ptr->file)
|
||||
std::fprintf(log, "-0x%p -> %zu bytes allocated at %s:%u\n", reinterpret_cast<nzUInt8*>(ptr) + sizeof(Block), ptr->size, ptr->file, ptr->line);
|
||||
std::size_t size;
|
||||
const char* file;
|
||||
Block* prev;
|
||||
Block* next;
|
||||
bool array;
|
||||
unsigned int line;
|
||||
unsigned int magic;
|
||||
};
|
||||
|
||||
bool s_allocationFilling = true;
|
||||
bool s_allocationLogging = false;
|
||||
bool s_initialized = false;
|
||||
const char* s_logFileName = "NazaraMemory.log";
|
||||
thread_local const char* s_nextFreeFile = "(Internal error)";
|
||||
thread_local unsigned int s_nextFreeLine = 0;
|
||||
|
||||
Block s_list =
|
||||
{
|
||||
0,
|
||||
nullptr,
|
||||
&s_list,
|
||||
&s_list,
|
||||
false,
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
unsigned int s_allocationCount = 0;
|
||||
unsigned int s_allocatedBlock = 0;
|
||||
std::size_t s_allocatedSize = 0;
|
||||
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
CRITICAL_SECTION s_mutex;
|
||||
#elif defined(NAZARA_PLATFORM_POSIX)
|
||||
pthread_mutex_t s_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
#endif
|
||||
}
|
||||
|
||||
MemoryManager::MemoryManager()
|
||||
{
|
||||
}
|
||||
|
||||
MemoryManager::~MemoryManager()
|
||||
{
|
||||
Uninitialize();
|
||||
}
|
||||
|
||||
void* MemoryManager::Allocate(std::size_t size, bool multi, const char* file, unsigned int line)
|
||||
{
|
||||
if (!s_initialized)
|
||||
Initialize();
|
||||
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
EnterCriticalSection(&s_mutex);
|
||||
#elif defined(NAZARA_PLATFORM_POSIX)
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
#endif
|
||||
|
||||
Block* ptr = reinterpret_cast<Block*>(std::malloc(size+sizeof(Block)));
|
||||
if (!ptr)
|
||||
{
|
||||
char timeStr[23];
|
||||
TimeInfo(timeStr);
|
||||
|
||||
FILE* log = std::fopen(s_logFileName, "a");
|
||||
|
||||
if (file)
|
||||
std::fprintf(log, "%s Failed to allocate %zu bytes at %s:%u\n", timeStr, size, file, line);
|
||||
else
|
||||
std::fprintf(log, "-0x%p -> %zu bytes allocated at unknown position\n", reinterpret_cast<nzUInt8*>(ptr) + sizeof(Block), ptr->size);
|
||||
std::fprintf(log, "%s Failed to allocate %zu bytes at unknown position\n", timeStr, size);
|
||||
|
||||
void* pointer = ptr;
|
||||
ptr = ptr->next;
|
||||
std::fclose(log);
|
||||
|
||||
std::free(pointer);
|
||||
throw std::bad_alloc();
|
||||
return nullptr; // Ça me rassure d'avoir un return, aussi inutile soit-il
|
||||
}
|
||||
|
||||
std::fprintf(log, "\n%u blocks leaked (%zu bytes)", s_allocatedBlock, s_allocatedSize);
|
||||
ptr->array = multi;
|
||||
ptr->file = file;
|
||||
ptr->line = line;
|
||||
ptr->size = size;
|
||||
ptr->magic = s_allocatedId;
|
||||
|
||||
ptr->prev = s_list.prev;
|
||||
ptr->next = &s_list;
|
||||
s_list.prev->next = ptr;
|
||||
s_list.prev = ptr;
|
||||
|
||||
s_allocatedBlock++;
|
||||
s_allocatedSize += size;
|
||||
s_allocationCount++;
|
||||
|
||||
if (s_allocationFilling)
|
||||
{
|
||||
UInt8* data = reinterpret_cast<UInt8*>(ptr) + sizeof(Block);
|
||||
std::memset(data, 0xFF, size);
|
||||
}
|
||||
|
||||
if (s_allocationLogging)
|
||||
{
|
||||
char timeStr[23];
|
||||
TimeInfo(timeStr);
|
||||
|
||||
FILE* log = std::fopen(s_logFileName, "a");
|
||||
|
||||
if (file)
|
||||
std::fprintf(log, "%s Allocated %zu bytes at %s:%u\n", timeStr, size, file, line);
|
||||
else
|
||||
std::fprintf(log, "%s Allocated %zu bytes at unknown position\n", timeStr, size);
|
||||
|
||||
std::fclose(log);
|
||||
}
|
||||
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
LeaveCriticalSection(&s_mutex);
|
||||
#elif defined(NAZARA_PLATFORM_POSIX)
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
#endif
|
||||
|
||||
return reinterpret_cast<UInt8*>(ptr) + sizeof(Block);
|
||||
}
|
||||
|
||||
std::fclose(log);
|
||||
void MemoryManager::EnableAllocationFilling(bool allocationFilling)
|
||||
{
|
||||
s_allocationFilling = allocationFilling;
|
||||
}
|
||||
|
||||
void MemoryManager::EnableAllocationLogging(bool logAllocations)
|
||||
{
|
||||
s_allocationLogging = logAllocations;
|
||||
}
|
||||
|
||||
void MemoryManager::Free(void* pointer, bool multi)
|
||||
{
|
||||
if (!pointer)
|
||||
return;
|
||||
|
||||
Block* ptr = reinterpret_cast<Block*>(reinterpret_cast<UInt8*>(pointer) - sizeof(Block));
|
||||
if (ptr->magic != s_allocatedId)
|
||||
{
|
||||
char timeStr[23];
|
||||
TimeInfo(timeStr);
|
||||
|
||||
FILE* log = std::fopen(s_logFileName, "a");
|
||||
|
||||
const char* error = (ptr->magic == s_freedId) ? "double-delete" : "possible delete of dangling pointer";
|
||||
if (s_nextFreeFile)
|
||||
std::fprintf(log, "%s Warning: %s at %s:%u\n", timeStr, error, s_nextFreeFile, s_nextFreeLine);
|
||||
else
|
||||
std::fprintf(log, "%s Warning: %s at unknown position\n", timeStr, error);
|
||||
|
||||
std::fclose(log);
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
EnterCriticalSection(&s_mutex);
|
||||
#elif defined(NAZARA_PLATFORM_POSIX)
|
||||
pthread_mutex_lock(&s_mutex);
|
||||
#endif
|
||||
|
||||
if (ptr->array != multi)
|
||||
{
|
||||
char timeStr[23];
|
||||
TimeInfo(timeStr);
|
||||
|
||||
FILE* log = std::fopen(s_logFileName, "a");
|
||||
|
||||
const char* error = (multi) ? "delete[] after new" : "delete after new[]";
|
||||
if (s_nextFreeFile)
|
||||
std::fprintf(log, "%s Warning: %s at %s:%u\n", timeStr, error, s_nextFreeFile, s_nextFreeLine);
|
||||
else
|
||||
std::fprintf(log, "%s Warning: %s at unknown position\n", timeStr, error);
|
||||
|
||||
std::fclose(log);
|
||||
}
|
||||
|
||||
ptr->magic = s_freedId;
|
||||
ptr->prev->next = ptr->next;
|
||||
ptr->next->prev = ptr->prev;
|
||||
|
||||
s_allocatedBlock--;
|
||||
s_allocatedSize -= ptr->size;
|
||||
|
||||
if (s_allocationFilling)
|
||||
{
|
||||
UInt8* data = reinterpret_cast<UInt8*>(ptr) + sizeof(Block);
|
||||
std::memset(data, 0xFF, ptr->size);
|
||||
}
|
||||
|
||||
std::free(ptr);
|
||||
|
||||
s_nextFreeFile = nullptr;
|
||||
s_nextFreeLine = 0;
|
||||
|
||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||
LeaveCriticalSection(&s_mutex);
|
||||
#elif defined(NAZARA_PLATFORM_POSIX)
|
||||
pthread_mutex_unlock(&s_mutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned int MemoryManager::GetAllocatedBlockCount()
|
||||
{
|
||||
return s_allocatedBlock;
|
||||
}
|
||||
|
||||
std::size_t MemoryManager::GetAllocatedSize()
|
||||
{
|
||||
return s_allocatedSize;
|
||||
}
|
||||
|
||||
unsigned int MemoryManager::GetAllocationCount()
|
||||
{
|
||||
return s_allocationCount;
|
||||
}
|
||||
|
||||
bool MemoryManager::IsAllocationFillingEnabled()
|
||||
{
|
||||
return s_allocationFilling;
|
||||
}
|
||||
|
||||
bool MemoryManager::IsAllocationLoggingEnabled()
|
||||
{
|
||||
return s_allocationLogging;
|
||||
}
|
||||
|
||||
void MemoryManager::NextFree(const char* file, unsigned int line)
|
||||
{
|
||||
s_nextFreeFile = file;
|
||||
s_nextFreeLine = line;
|
||||
}
|
||||
|
||||
void MemoryManager::Initialize()
|
||||
{
|
||||
char timeStr[23];
|
||||
TimeInfo(timeStr);
|
||||
|
||||
FILE* file = std::fopen(s_logFileName, "w");
|
||||
std::fprintf(file, "%s ==============================\n", timeStr);
|
||||
std::fprintf(file, "%s Nazara Memory Leak Tracker \n", timeStr);
|
||||
std::fprintf(file, "%s ==============================\n", timeStr);
|
||||
std::fclose(file);
|
||||
|
||||
if (std::atexit(Uninitialize) != 0)
|
||||
{
|
||||
static MemoryManager manager;
|
||||
}
|
||||
|
||||
#ifdef NAZARA_PLATFORM_WINDOWS
|
||||
InitializeCriticalSection(&s_mutex);
|
||||
//#elif defined(NAZARA_PLATFORM_POSIX) is already done in the namespace
|
||||
#endif
|
||||
|
||||
s_initialized = true;
|
||||
}
|
||||
|
||||
void MemoryManager::TimeInfo(char buffer[23])
|
||||
{
|
||||
time_t currentTime = std::time(nullptr);
|
||||
std::strftime(buffer, 23, "%d/%m/%Y - %H:%M:%S:", std::localtime(¤tTime));
|
||||
}
|
||||
|
||||
void MemoryManager::Uninitialize()
|
||||
{
|
||||
#ifdef NAZARA_PLATFORM_WINDOWS
|
||||
DeleteCriticalSection(&s_mutex);
|
||||
#elif defined(NAZARA_PLATFORM_POSIX)
|
||||
pthread_mutex_destroy(&s_mutex);
|
||||
#endif
|
||||
|
||||
FILE* log = std::fopen(s_logFileName, "a");
|
||||
|
||||
char timeStr[23];
|
||||
TimeInfo(timeStr);
|
||||
|
||||
std::fprintf(log, "%s Application finished, checking leaks...\n", timeStr);
|
||||
|
||||
if (s_allocatedBlock == 0)
|
||||
{
|
||||
std::fprintf(log, "%s ==============================\n", timeStr);
|
||||
std::fprintf(log, "%s No leak detected \n", timeStr);
|
||||
std::fprintf(log, "%s ==============================", timeStr);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::fprintf(log, "%s ==============================\n", timeStr);
|
||||
std::fprintf(log, "%s Leaks have been detected \n", timeStr);
|
||||
std::fprintf(log, "%s ==============================\n\n", timeStr);
|
||||
std::fputs("Leak list:\n", log);
|
||||
|
||||
Block* ptr = s_list.next;
|
||||
while (ptr != &s_list)
|
||||
{
|
||||
if (ptr->file)
|
||||
std::fprintf(log, "-0x%p -> %zu bytes allocated at %s:%u\n", reinterpret_cast<UInt8*>(ptr) + sizeof(Block), ptr->size, ptr->file, ptr->line);
|
||||
else
|
||||
std::fprintf(log, "-0x%p -> %zu bytes allocated at unknown position\n", reinterpret_cast<UInt8*>(ptr) + sizeof(Block), ptr->size);
|
||||
|
||||
void* pointer = ptr;
|
||||
ptr = ptr->next;
|
||||
|
||||
std::free(pointer);
|
||||
}
|
||||
|
||||
std::fprintf(log, "\n%u blocks leaked (%zu bytes)", s_allocatedBlock, s_allocatedSize);
|
||||
}
|
||||
|
||||
std::fclose(log);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,47 +7,50 @@
|
||||
#include <cstring>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzMemoryStream::NzMemoryStream(const void* ptr, nzUInt64 size) :
|
||||
m_ptr(reinterpret_cast<const nzUInt8*>(ptr)),
|
||||
m_pos(0),
|
||||
m_size(size)
|
||||
namespace Nz
|
||||
{
|
||||
}
|
||||
|
||||
NzMemoryStream::~NzMemoryStream()
|
||||
{
|
||||
}
|
||||
|
||||
bool NzMemoryStream::EndOfStream() const
|
||||
{
|
||||
return m_pos == m_size;
|
||||
}
|
||||
|
||||
nzUInt64 NzMemoryStream::GetCursorPos() const
|
||||
{
|
||||
return m_pos;
|
||||
}
|
||||
|
||||
nzUInt64 NzMemoryStream::GetSize() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
std::size_t NzMemoryStream::Read(void* buffer, std::size_t size)
|
||||
{
|
||||
unsigned int readSize = std::min(static_cast<unsigned int>(size), static_cast<unsigned int>(m_size-m_pos));
|
||||
|
||||
if (buffer)
|
||||
std::memcpy(buffer, &m_ptr[m_pos], readSize);
|
||||
|
||||
m_pos += readSize;
|
||||
|
||||
return readSize;
|
||||
}
|
||||
|
||||
bool NzMemoryStream::SetCursorPos(nzUInt64 offset)
|
||||
{
|
||||
m_pos = std::min(offset, m_size);
|
||||
|
||||
return true;
|
||||
MemoryStream::MemoryStream(const void* ptr, UInt64 size) :
|
||||
m_ptr(reinterpret_cast<const UInt8*>(ptr)),
|
||||
m_pos(0),
|
||||
m_size(size)
|
||||
{
|
||||
}
|
||||
|
||||
MemoryStream::~MemoryStream()
|
||||
{
|
||||
}
|
||||
|
||||
bool MemoryStream::EndOfStream() const
|
||||
{
|
||||
return m_pos == m_size;
|
||||
}
|
||||
|
||||
UInt64 MemoryStream::GetCursorPos() const
|
||||
{
|
||||
return m_pos;
|
||||
}
|
||||
|
||||
UInt64 MemoryStream::GetSize() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
std::size_t MemoryStream::Read(void* buffer, std::size_t size)
|
||||
{
|
||||
unsigned int readSize = std::min(static_cast<unsigned int>(size), static_cast<unsigned int>(m_size-m_pos));
|
||||
|
||||
if (buffer)
|
||||
std::memcpy(buffer, &m_ptr[m_pos], readSize);
|
||||
|
||||
m_pos += readSize;
|
||||
|
||||
return readSize;
|
||||
}
|
||||
|
||||
bool MemoryStream::SetCursorPos(UInt64 offset)
|
||||
{
|
||||
m_pos = std::min(offset, m_size);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,27 +14,30 @@
|
||||
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzMutex::NzMutex()
|
||||
namespace Nz
|
||||
{
|
||||
m_impl = new NzMutexImpl;
|
||||
}
|
||||
Mutex::Mutex()
|
||||
{
|
||||
m_impl = new MutexImpl;
|
||||
}
|
||||
|
||||
NzMutex::~NzMutex()
|
||||
{
|
||||
delete m_impl;
|
||||
}
|
||||
Mutex::~Mutex()
|
||||
{
|
||||
delete m_impl;
|
||||
}
|
||||
|
||||
void NzMutex::Lock()
|
||||
{
|
||||
m_impl->Lock();
|
||||
}
|
||||
void Mutex::Lock()
|
||||
{
|
||||
m_impl->Lock();
|
||||
}
|
||||
|
||||
bool NzMutex::TryLock()
|
||||
{
|
||||
return m_impl->TryLock();
|
||||
}
|
||||
bool Mutex::TryLock()
|
||||
{
|
||||
return m_impl->TryLock();
|
||||
}
|
||||
|
||||
void NzMutex::Unlock()
|
||||
{
|
||||
m_impl->Unlock();
|
||||
void Mutex::Unlock()
|
||||
{
|
||||
m_impl->Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,436 +10,439 @@
|
||||
#include <new>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzParameterList::NzParameterList(const NzParameterList& list)
|
||||
namespace Nz
|
||||
{
|
||||
operator=(list);
|
||||
}
|
||||
|
||||
NzParameterList::~NzParameterList()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
void NzParameterList::Clear()
|
||||
{
|
||||
for (auto it = m_parameters.begin(); it != m_parameters.end(); ++it)
|
||||
DestroyValue(it->second);
|
||||
|
||||
m_parameters.clear();
|
||||
}
|
||||
|
||||
bool NzParameterList::GetBooleanParameter(const NzString& name, bool* value) const
|
||||
{
|
||||
auto it = m_parameters.find(name);
|
||||
if (it == m_parameters.end())
|
||||
ParameterList::ParameterList(const ParameterList& list)
|
||||
{
|
||||
NazaraError("Parameter \"" + name + "\" is not present");
|
||||
return false;
|
||||
operator=(list);
|
||||
}
|
||||
|
||||
switch (it->second.type)
|
||||
ParameterList::~ParameterList()
|
||||
{
|
||||
case nzParameterType_Boolean:
|
||||
*value = it->second.value.boolVal;
|
||||
return true;
|
||||
Clear();
|
||||
}
|
||||
|
||||
case nzParameterType_Integer:
|
||||
*value = (it->second.value.intVal != 0);
|
||||
return true;
|
||||
void ParameterList::Clear()
|
||||
{
|
||||
for (auto it = m_parameters.begin(); it != m_parameters.end(); ++it)
|
||||
DestroyValue(it->second);
|
||||
|
||||
case nzParameterType_String:
|
||||
m_parameters.clear();
|
||||
}
|
||||
|
||||
bool ParameterList::GetBooleanParameter(const String& name, bool* value) const
|
||||
{
|
||||
auto it = m_parameters.find(name);
|
||||
if (it == m_parameters.end())
|
||||
{
|
||||
bool converted;
|
||||
if (it->second.value.stringVal.ToBool(&converted, NzString::CaseInsensitive))
|
||||
{
|
||||
*value = converted;
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case nzParameterType_Float:
|
||||
case nzParameterType_None:
|
||||
case nzParameterType_Pointer:
|
||||
case nzParameterType_Userdata:
|
||||
break;
|
||||
}
|
||||
|
||||
NazaraError("Parameter value is not representable as a boolean");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NzParameterList::GetFloatParameter(const NzString& name, float* value) const
|
||||
{
|
||||
auto it = m_parameters.find(name);
|
||||
if (it == m_parameters.end())
|
||||
{
|
||||
NazaraError("Parameter \"" + name + "\" is not present");
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (it->second.type)
|
||||
{
|
||||
case nzParameterType_Float:
|
||||
*value = it->second.value.floatVal;
|
||||
return true;
|
||||
|
||||
case nzParameterType_Integer:
|
||||
*value = static_cast<float>(it->second.value.intVal);
|
||||
return true;
|
||||
|
||||
case nzParameterType_String:
|
||||
{
|
||||
double converted;
|
||||
if (it->second.value.stringVal.ToDouble(&converted))
|
||||
{
|
||||
*value = static_cast<float>(converted);
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case nzParameterType_Boolean:
|
||||
case nzParameterType_None:
|
||||
case nzParameterType_Pointer:
|
||||
case nzParameterType_Userdata:
|
||||
break;
|
||||
}
|
||||
|
||||
NazaraError("Parameter value is not representable as a float");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NzParameterList::GetIntegerParameter(const NzString& name, int* value) const
|
||||
{
|
||||
auto it = m_parameters.find(name);
|
||||
if (it == m_parameters.end())
|
||||
{
|
||||
NazaraError("Parameter \"" + name + "\" is not present");
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (it->second.type)
|
||||
{
|
||||
case nzParameterType_Boolean:
|
||||
*value = (it->second.value.boolVal) ? 1 : 0;
|
||||
return true;
|
||||
|
||||
case nzParameterType_Float:
|
||||
*value = static_cast<int>(it->second.value.floatVal);
|
||||
return true;
|
||||
|
||||
case nzParameterType_Integer:
|
||||
*value = it->second.value.intVal;
|
||||
NazaraError("Parameter \"" + name + "\" is not present");
|
||||
return false;
|
||||
|
||||
case nzParameterType_String:
|
||||
{
|
||||
long long converted;
|
||||
if (it->second.value.stringVal.ToInteger(&converted))
|
||||
{
|
||||
if (converted <= std::numeric_limits<int>::max() && converted >= std::numeric_limits<int>::min())
|
||||
{
|
||||
*value = static_cast<int>(converted);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case nzParameterType_None:
|
||||
case nzParameterType_Pointer:
|
||||
case nzParameterType_Userdata:
|
||||
break;
|
||||
}
|
||||
|
||||
NazaraError("Parameter value is not representable as a integer");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NzParameterList::GetParameterType(const NzString& name, nzParameterType* type) const
|
||||
{
|
||||
auto it = m_parameters.find(name);
|
||||
if (it == m_parameters.end())
|
||||
return false;
|
||||
|
||||
*type = it->second.type;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzParameterList::GetPointerParameter(const NzString& name, void** value) const
|
||||
{
|
||||
auto it = m_parameters.find(name);
|
||||
if (it == m_parameters.end())
|
||||
{
|
||||
NazaraError("Parameter \"" + name + "\" is not present");
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (it->second.type)
|
||||
{
|
||||
case nzParameterType_Pointer:
|
||||
*value = it->second.value.ptrVal;
|
||||
return true;
|
||||
|
||||
case nzParameterType_Userdata:
|
||||
*value = it->second.value.userdataVal->ptr;
|
||||
return true;
|
||||
|
||||
case nzParameterType_Boolean:
|
||||
case nzParameterType_Float:
|
||||
case nzParameterType_Integer:
|
||||
case nzParameterType_None:
|
||||
case nzParameterType_String:
|
||||
break;
|
||||
}
|
||||
|
||||
NazaraError("Parameter value is not a pointer");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NzParameterList::GetStringParameter(const NzString& name, NzString* value) const
|
||||
{
|
||||
auto it = m_parameters.find(name);
|
||||
if (it == m_parameters.end())
|
||||
{
|
||||
NazaraError("Parameter \"" + name + "\" is not present");
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (it->second.type)
|
||||
{
|
||||
case nzParameterType_Boolean:
|
||||
*value = NzString::Boolean(it->second.value.boolVal);
|
||||
return true;
|
||||
|
||||
case nzParameterType_Float:
|
||||
*value = NzString::Number(it->second.value.floatVal);
|
||||
return true;
|
||||
|
||||
case nzParameterType_Integer:
|
||||
*value = NzString::Number(it->second.value.intVal);
|
||||
return true;
|
||||
|
||||
case nzParameterType_String:
|
||||
*value = it->second.value.stringVal;
|
||||
return true;
|
||||
|
||||
case nzParameterType_Pointer:
|
||||
*value = NzString::Pointer(it->second.value.ptrVal);
|
||||
return true;
|
||||
|
||||
case nzParameterType_Userdata:
|
||||
*value = NzString::Pointer(it->second.value.userdataVal->ptr);
|
||||
return true;
|
||||
|
||||
case nzParameterType_None:
|
||||
*value = NzString();
|
||||
return true;
|
||||
}
|
||||
|
||||
NazaraInternalError("Parameter value is not valid");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NzParameterList::GetUserdataParameter(const NzString& name, void** value) const
|
||||
{
|
||||
auto it = m_parameters.find(name);
|
||||
if (it == m_parameters.end())
|
||||
{
|
||||
NazaraError("Parameter \"" + name + "\" is not present");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (it->second.type == nzParameterType_Userdata)
|
||||
{
|
||||
*value = it->second.value.userdataVal->ptr;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
NazaraError("Parameter value is not a userdata");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool NzParameterList::HasParameter(const NzString& name) const
|
||||
{
|
||||
return m_parameters.find(name) != m_parameters.end();
|
||||
}
|
||||
|
||||
void NzParameterList::RemoveParameter(const NzString& name)
|
||||
{
|
||||
auto it = m_parameters.find(name);
|
||||
if (it != m_parameters.end())
|
||||
{
|
||||
DestroyValue(it->second);
|
||||
m_parameters.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void NzParameterList::SetParameter(const NzString& name)
|
||||
{
|
||||
std::pair<ParameterMap::iterator, bool> pair = m_parameters.insert(std::make_pair(name, Parameter()));
|
||||
Parameter& parameter = pair.first->second;
|
||||
|
||||
if (!pair.second)
|
||||
DestroyValue(parameter);
|
||||
|
||||
parameter.type = nzParameterType_None;
|
||||
}
|
||||
|
||||
void NzParameterList::SetParameter(const NzString& name, const NzString& value)
|
||||
{
|
||||
std::pair<ParameterMap::iterator, bool> pair = m_parameters.insert(std::make_pair(name, Parameter()));
|
||||
Parameter& parameter = pair.first->second;
|
||||
|
||||
if (!pair.second)
|
||||
DestroyValue(parameter);
|
||||
|
||||
parameter.type = nzParameterType_String;
|
||||
|
||||
NzPlacementNew<NzString>(¶meter.value.stringVal, value);
|
||||
}
|
||||
|
||||
void NzParameterList::SetParameter(const NzString& name, const char* value)
|
||||
{
|
||||
std::pair<ParameterMap::iterator, bool> pair = m_parameters.insert(std::make_pair(name, Parameter()));
|
||||
Parameter& parameter = pair.first->second;
|
||||
|
||||
if (!pair.second)
|
||||
DestroyValue(parameter);
|
||||
|
||||
parameter.type = nzParameterType_String;
|
||||
|
||||
NzPlacementNew<NzString>(¶meter.value.stringVal, value);
|
||||
}
|
||||
|
||||
void NzParameterList::SetParameter(const NzString& name, void* value)
|
||||
{
|
||||
std::pair<ParameterMap::iterator, bool> pair = m_parameters.insert(std::make_pair(name, Parameter()));
|
||||
Parameter& parameter = pair.first->second;
|
||||
|
||||
if (!pair.second)
|
||||
DestroyValue(parameter);
|
||||
|
||||
parameter.type = nzParameterType_Pointer;
|
||||
parameter.value.ptrVal = value;
|
||||
}
|
||||
|
||||
void NzParameterList::SetParameter(const NzString& name, void* value, Destructor destructor)
|
||||
{
|
||||
std::pair<ParameterMap::iterator, bool> pair = m_parameters.insert(std::make_pair(name, Parameter()));
|
||||
Parameter& parameter = pair.first->second;
|
||||
|
||||
if (!pair.second)
|
||||
DestroyValue(parameter);
|
||||
|
||||
parameter.type = nzParameterType_Userdata;
|
||||
parameter.value.userdataVal = new Parameter::UserdataValue(destructor, value);
|
||||
}
|
||||
|
||||
void NzParameterList::SetParameter(const NzString& name, bool value)
|
||||
{
|
||||
std::pair<ParameterMap::iterator, bool> pair = m_parameters.insert(std::make_pair(name, Parameter()));
|
||||
Parameter& parameter = pair.first->second;
|
||||
|
||||
if (!pair.second)
|
||||
DestroyValue(parameter);
|
||||
|
||||
parameter.type = nzParameterType_Boolean;
|
||||
parameter.value.boolVal = value;
|
||||
}
|
||||
|
||||
void NzParameterList::SetParameter(const NzString& name, float value)
|
||||
{
|
||||
std::pair<ParameterMap::iterator, bool> pair = m_parameters.insert(std::make_pair(name, Parameter()));
|
||||
Parameter& parameter = pair.first->second;
|
||||
|
||||
if (!pair.second)
|
||||
DestroyValue(parameter);
|
||||
|
||||
parameter.type = nzParameterType_Float;
|
||||
parameter.value.floatVal = value;
|
||||
}
|
||||
|
||||
void NzParameterList::SetParameter(const NzString& name, int value)
|
||||
{
|
||||
std::pair<ParameterMap::iterator, bool> pair = m_parameters.insert(std::make_pair(name, Parameter()));
|
||||
Parameter& parameter = pair.first->second;
|
||||
|
||||
if (!pair.second)
|
||||
DestroyValue(parameter);
|
||||
|
||||
parameter.type = nzParameterType_Integer;
|
||||
parameter.value.intVal = value;
|
||||
}
|
||||
|
||||
NzParameterList& NzParameterList::operator=(const NzParameterList& list)
|
||||
{
|
||||
Clear();
|
||||
|
||||
for (auto it = list.m_parameters.begin(); it != list.m_parameters.end(); ++it)
|
||||
{
|
||||
Parameter& parameter = m_parameters[it->first];
|
||||
|
||||
switch (it->second.type)
|
||||
{
|
||||
case nzParameterType_Boolean:
|
||||
case nzParameterType_Float:
|
||||
case nzParameterType_Integer:
|
||||
case nzParameterType_Pointer:
|
||||
std::memcpy(¶meter, &it->second, sizeof(Parameter));
|
||||
break;
|
||||
case ParameterType_Boolean:
|
||||
*value = it->second.value.boolVal;
|
||||
return true;
|
||||
|
||||
case nzParameterType_String:
|
||||
parameter.type = nzParameterType_String;
|
||||
case ParameterType_Integer:
|
||||
*value = (it->second.value.intVal != 0);
|
||||
return true;
|
||||
|
||||
NzPlacementNew<NzString>(¶meter.value.stringVal, it->second.value.stringVal);
|
||||
break;
|
||||
|
||||
case nzParameterType_Userdata:
|
||||
parameter.type = nzParameterType_Userdata;
|
||||
parameter.value.userdataVal = it->second.value.userdataVal;
|
||||
++(parameter.value.userdataVal->counter);
|
||||
break;
|
||||
|
||||
case nzParameterType_None:
|
||||
parameter.type = nzParameterType_None;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void NzParameterList::DestroyValue(Parameter& parameter)
|
||||
{
|
||||
switch (parameter.type)
|
||||
{
|
||||
case nzParameterType_String:
|
||||
parameter.value.stringVal.~NzString();
|
||||
break;
|
||||
|
||||
case nzParameterType_Userdata:
|
||||
{
|
||||
Parameter::UserdataValue* userdata = parameter.value.userdataVal;
|
||||
if (--userdata->counter == 0)
|
||||
case ParameterType_String:
|
||||
{
|
||||
userdata->destructor(userdata->ptr);
|
||||
delete userdata;
|
||||
bool converted;
|
||||
if (it->second.value.stringVal.ToBool(&converted, String::CaseInsensitive))
|
||||
{
|
||||
*value = converted;
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case ParameterType_Float:
|
||||
case ParameterType_None:
|
||||
case ParameterType_Pointer:
|
||||
case ParameterType_Userdata:
|
||||
break;
|
||||
}
|
||||
|
||||
case nzParameterType_Boolean:
|
||||
case nzParameterType_Float:
|
||||
case nzParameterType_Integer:
|
||||
case nzParameterType_None:
|
||||
case nzParameterType_Pointer:
|
||||
break;
|
||||
NazaraError("Parameter value is not representable as a boolean");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ParameterList::GetFloatParameter(const String& name, float* value) const
|
||||
{
|
||||
auto it = m_parameters.find(name);
|
||||
if (it == m_parameters.end())
|
||||
{
|
||||
NazaraError("Parameter \"" + name + "\" is not present");
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (it->second.type)
|
||||
{
|
||||
case ParameterType_Float:
|
||||
*value = it->second.value.floatVal;
|
||||
return true;
|
||||
|
||||
case ParameterType_Integer:
|
||||
*value = static_cast<float>(it->second.value.intVal);
|
||||
return true;
|
||||
|
||||
case ParameterType_String:
|
||||
{
|
||||
double converted;
|
||||
if (it->second.value.stringVal.ToDouble(&converted))
|
||||
{
|
||||
*value = static_cast<float>(converted);
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ParameterType_Boolean:
|
||||
case ParameterType_None:
|
||||
case ParameterType_Pointer:
|
||||
case ParameterType_Userdata:
|
||||
break;
|
||||
}
|
||||
|
||||
NazaraError("Parameter value is not representable as a float");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ParameterList::GetIntegerParameter(const String& name, int* value) const
|
||||
{
|
||||
auto it = m_parameters.find(name);
|
||||
if (it == m_parameters.end())
|
||||
{
|
||||
NazaraError("Parameter \"" + name + "\" is not present");
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (it->second.type)
|
||||
{
|
||||
case ParameterType_Boolean:
|
||||
*value = (it->second.value.boolVal) ? 1 : 0;
|
||||
return true;
|
||||
|
||||
case ParameterType_Float:
|
||||
*value = static_cast<int>(it->second.value.floatVal);
|
||||
return true;
|
||||
|
||||
case ParameterType_Integer:
|
||||
*value = it->second.value.intVal;
|
||||
return false;
|
||||
|
||||
case ParameterType_String:
|
||||
{
|
||||
long long converted;
|
||||
if (it->second.value.stringVal.ToInteger(&converted))
|
||||
{
|
||||
if (converted <= std::numeric_limits<int>::max() && converted >= std::numeric_limits<int>::min())
|
||||
{
|
||||
*value = static_cast<int>(converted);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ParameterType_None:
|
||||
case ParameterType_Pointer:
|
||||
case ParameterType_Userdata:
|
||||
break;
|
||||
}
|
||||
|
||||
NazaraError("Parameter value is not representable as a integer");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ParameterList::GetParameterType(const String& name, ParameterType* type) const
|
||||
{
|
||||
auto it = m_parameters.find(name);
|
||||
if (it == m_parameters.end())
|
||||
return false;
|
||||
|
||||
*type = it->second.type;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParameterList::GetPointerParameter(const String& name, void** value) const
|
||||
{
|
||||
auto it = m_parameters.find(name);
|
||||
if (it == m_parameters.end())
|
||||
{
|
||||
NazaraError("Parameter \"" + name + "\" is not present");
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (it->second.type)
|
||||
{
|
||||
case ParameterType_Pointer:
|
||||
*value = it->second.value.ptrVal;
|
||||
return true;
|
||||
|
||||
case ParameterType_Userdata:
|
||||
*value = it->second.value.userdataVal->ptr;
|
||||
return true;
|
||||
|
||||
case ParameterType_Boolean:
|
||||
case ParameterType_Float:
|
||||
case ParameterType_Integer:
|
||||
case ParameterType_None:
|
||||
case ParameterType_String:
|
||||
break;
|
||||
}
|
||||
|
||||
NazaraError("Parameter value is not a pointer");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ParameterList::GetStringParameter(const String& name, String* value) const
|
||||
{
|
||||
auto it = m_parameters.find(name);
|
||||
if (it == m_parameters.end())
|
||||
{
|
||||
NazaraError("Parameter \"" + name + "\" is not present");
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (it->second.type)
|
||||
{
|
||||
case ParameterType_Boolean:
|
||||
*value = String::Boolean(it->second.value.boolVal);
|
||||
return true;
|
||||
|
||||
case ParameterType_Float:
|
||||
*value = String::Number(it->second.value.floatVal);
|
||||
return true;
|
||||
|
||||
case ParameterType_Integer:
|
||||
*value = String::Number(it->second.value.intVal);
|
||||
return true;
|
||||
|
||||
case ParameterType_String:
|
||||
*value = it->second.value.stringVal;
|
||||
return true;
|
||||
|
||||
case ParameterType_Pointer:
|
||||
*value = String::Pointer(it->second.value.ptrVal);
|
||||
return true;
|
||||
|
||||
case ParameterType_Userdata:
|
||||
*value = String::Pointer(it->second.value.userdataVal->ptr);
|
||||
return true;
|
||||
|
||||
case ParameterType_None:
|
||||
*value = String();
|
||||
return true;
|
||||
}
|
||||
|
||||
NazaraInternalError("Parameter value is not valid");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ParameterList::GetUserdataParameter(const String& name, void** value) const
|
||||
{
|
||||
auto it = m_parameters.find(name);
|
||||
if (it == m_parameters.end())
|
||||
{
|
||||
NazaraError("Parameter \"" + name + "\" is not present");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (it->second.type == ParameterType_Userdata)
|
||||
{
|
||||
*value = it->second.value.userdataVal->ptr;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
NazaraError("Parameter value is not a userdata");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ParameterList::HasParameter(const String& name) const
|
||||
{
|
||||
return m_parameters.find(name) != m_parameters.end();
|
||||
}
|
||||
|
||||
void ParameterList::RemoveParameter(const String& name)
|
||||
{
|
||||
auto it = m_parameters.find(name);
|
||||
if (it != m_parameters.end())
|
||||
{
|
||||
DestroyValue(it->second);
|
||||
m_parameters.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void ParameterList::SetParameter(const String& name)
|
||||
{
|
||||
std::pair<ParameterMap::iterator, bool> pair = m_parameters.insert(std::make_pair(name, Parameter()));
|
||||
Parameter& parameter = pair.first->second;
|
||||
|
||||
if (!pair.second)
|
||||
DestroyValue(parameter);
|
||||
|
||||
parameter.type = ParameterType_None;
|
||||
}
|
||||
|
||||
void ParameterList::SetParameter(const String& name, const String& value)
|
||||
{
|
||||
std::pair<ParameterMap::iterator, bool> pair = m_parameters.insert(std::make_pair(name, Parameter()));
|
||||
Parameter& parameter = pair.first->second;
|
||||
|
||||
if (!pair.second)
|
||||
DestroyValue(parameter);
|
||||
|
||||
parameter.type = ParameterType_String;
|
||||
|
||||
PlacementNew<String>(¶meter.value.stringVal, value);
|
||||
}
|
||||
|
||||
void ParameterList::SetParameter(const String& name, const char* value)
|
||||
{
|
||||
std::pair<ParameterMap::iterator, bool> pair = m_parameters.insert(std::make_pair(name, Parameter()));
|
||||
Parameter& parameter = pair.first->second;
|
||||
|
||||
if (!pair.second)
|
||||
DestroyValue(parameter);
|
||||
|
||||
parameter.type = ParameterType_String;
|
||||
|
||||
PlacementNew<String>(¶meter.value.stringVal, value);
|
||||
}
|
||||
|
||||
void ParameterList::SetParameter(const String& name, void* value)
|
||||
{
|
||||
std::pair<ParameterMap::iterator, bool> pair = m_parameters.insert(std::make_pair(name, Parameter()));
|
||||
Parameter& parameter = pair.first->second;
|
||||
|
||||
if (!pair.second)
|
||||
DestroyValue(parameter);
|
||||
|
||||
parameter.type = ParameterType_Pointer;
|
||||
parameter.value.ptrVal = value;
|
||||
}
|
||||
|
||||
void ParameterList::SetParameter(const String& name, void* value, Destructor destructor)
|
||||
{
|
||||
std::pair<ParameterMap::iterator, bool> pair = m_parameters.insert(std::make_pair(name, Parameter()));
|
||||
Parameter& parameter = pair.first->second;
|
||||
|
||||
if (!pair.second)
|
||||
DestroyValue(parameter);
|
||||
|
||||
parameter.type = ParameterType_Userdata;
|
||||
parameter.value.userdataVal = new Parameter::UserdataValue(destructor, value);
|
||||
}
|
||||
|
||||
void ParameterList::SetParameter(const String& name, bool value)
|
||||
{
|
||||
std::pair<ParameterMap::iterator, bool> pair = m_parameters.insert(std::make_pair(name, Parameter()));
|
||||
Parameter& parameter = pair.first->second;
|
||||
|
||||
if (!pair.second)
|
||||
DestroyValue(parameter);
|
||||
|
||||
parameter.type = ParameterType_Boolean;
|
||||
parameter.value.boolVal = value;
|
||||
}
|
||||
|
||||
void ParameterList::SetParameter(const String& name, float value)
|
||||
{
|
||||
std::pair<ParameterMap::iterator, bool> pair = m_parameters.insert(std::make_pair(name, Parameter()));
|
||||
Parameter& parameter = pair.first->second;
|
||||
|
||||
if (!pair.second)
|
||||
DestroyValue(parameter);
|
||||
|
||||
parameter.type = ParameterType_Float;
|
||||
parameter.value.floatVal = value;
|
||||
}
|
||||
|
||||
void ParameterList::SetParameter(const String& name, int value)
|
||||
{
|
||||
std::pair<ParameterMap::iterator, bool> pair = m_parameters.insert(std::make_pair(name, Parameter()));
|
||||
Parameter& parameter = pair.first->second;
|
||||
|
||||
if (!pair.second)
|
||||
DestroyValue(parameter);
|
||||
|
||||
parameter.type = ParameterType_Integer;
|
||||
parameter.value.intVal = value;
|
||||
}
|
||||
|
||||
ParameterList& ParameterList::operator=(const ParameterList& list)
|
||||
{
|
||||
Clear();
|
||||
|
||||
for (auto it = list.m_parameters.begin(); it != list.m_parameters.end(); ++it)
|
||||
{
|
||||
Parameter& parameter = m_parameters[it->first];
|
||||
|
||||
switch (it->second.type)
|
||||
{
|
||||
case ParameterType_Boolean:
|
||||
case ParameterType_Float:
|
||||
case ParameterType_Integer:
|
||||
case ParameterType_Pointer:
|
||||
std::memcpy(¶meter, &it->second, sizeof(Parameter));
|
||||
break;
|
||||
|
||||
case ParameterType_String:
|
||||
parameter.type = ParameterType_String;
|
||||
|
||||
PlacementNew<String>(¶meter.value.stringVal, it->second.value.stringVal);
|
||||
break;
|
||||
|
||||
case ParameterType_Userdata:
|
||||
parameter.type = ParameterType_Userdata;
|
||||
parameter.value.userdataVal = it->second.value.userdataVal;
|
||||
++(parameter.value.userdataVal->counter);
|
||||
break;
|
||||
|
||||
case ParameterType_None:
|
||||
parameter.type = ParameterType_None;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void ParameterList::DestroyValue(Parameter& parameter)
|
||||
{
|
||||
switch (parameter.type)
|
||||
{
|
||||
case ParameterType_String:
|
||||
parameter.value.stringVal.~String();
|
||||
break;
|
||||
|
||||
case ParameterType_Userdata:
|
||||
{
|
||||
Parameter::UserdataValue* userdata = parameter.value.userdataVal;
|
||||
if (--userdata->counter == 0)
|
||||
{
|
||||
userdata->destructor(userdata->ptr);
|
||||
delete userdata;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ParameterType_Boolean:
|
||||
case ParameterType_Float:
|
||||
case ParameterType_Integer:
|
||||
case ParameterType_None:
|
||||
case ParameterType_Pointer:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,176 +10,179 @@
|
||||
#include <memory>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
namespace
|
||||
namespace Nz
|
||||
{
|
||||
using PluginLoad = int (*)();
|
||||
using PluginUnload = void (*)();
|
||||
|
||||
NzString s_pluginFiles[] =
|
||||
namespace
|
||||
{
|
||||
"NazaraAssimp", // nzPlugin_Assimp
|
||||
"NazaraFreetype" // nzPlugin_FreeType
|
||||
};
|
||||
}
|
||||
using PluginLoad = int (*)();
|
||||
using PluginUnload = void (*)();
|
||||
|
||||
void NzPluginManager::AddDirectory(const NzString& directoryPath)
|
||||
{
|
||||
if (!Initialize())
|
||||
{
|
||||
NazaraError("Failed to initialize PluginManager");
|
||||
return;
|
||||
}
|
||||
|
||||
s_directories.insert(NzFile::AbsolutePath(directoryPath));
|
||||
}
|
||||
|
||||
bool NzPluginManager::Initialize()
|
||||
{
|
||||
if (s_initialized)
|
||||
return true;
|
||||
|
||||
s_initialized = true;
|
||||
|
||||
AddDirectory(".");
|
||||
AddDirectory("plugins");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzPluginManager::Mount(nzPlugin plugin)
|
||||
{
|
||||
return Mount(s_pluginFiles[plugin]);
|
||||
}
|
||||
|
||||
bool NzPluginManager::Mount(const NzString& pluginPath, bool appendExtension)
|
||||
{
|
||||
if (!Initialize())
|
||||
{
|
||||
NazaraError("Failed to initialize PluginManager");
|
||||
return false;
|
||||
}
|
||||
|
||||
NzString path = pluginPath;
|
||||
if (appendExtension && !path.EndsWith(NAZARA_DYNLIB_EXTENSION))
|
||||
path += NAZARA_DYNLIB_EXTENSION;
|
||||
|
||||
bool exists = false;
|
||||
if (!NzFile::IsAbsolute(path))
|
||||
{
|
||||
for (const NzString& dir : s_directories)
|
||||
String s_pluginFiles[] =
|
||||
{
|
||||
NzString testPath;
|
||||
testPath.Reserve(dir.GetSize() + path.GetSize() + 10);
|
||||
"NazaraAssimp", // Plugin_Assimp
|
||||
"NazaraFreetype" // Plugin_FreeType
|
||||
};
|
||||
}
|
||||
|
||||
testPath = dir;
|
||||
testPath += NAZARA_DIRECTORY_SEPARATOR;
|
||||
testPath += path;
|
||||
void PluginManager::AddDirectory(const String& directoryPath)
|
||||
{
|
||||
if (!Initialize())
|
||||
{
|
||||
NazaraError("Failed to initialize PluginManager");
|
||||
return;
|
||||
}
|
||||
|
||||
if (NzFile::Exists(testPath))
|
||||
s_directories.insert(File::AbsolutePath(directoryPath));
|
||||
}
|
||||
|
||||
bool PluginManager::Initialize()
|
||||
{
|
||||
if (s_initialized)
|
||||
return true;
|
||||
|
||||
s_initialized = true;
|
||||
|
||||
AddDirectory(".");
|
||||
AddDirectory("plugins");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PluginManager::Mount(Plugin plugin)
|
||||
{
|
||||
return Mount(s_pluginFiles[plugin]);
|
||||
}
|
||||
|
||||
bool PluginManager::Mount(const String& pluginPath, bool appendExtension)
|
||||
{
|
||||
if (!Initialize())
|
||||
{
|
||||
NazaraError("Failed to initialize PluginManager");
|
||||
return false;
|
||||
}
|
||||
|
||||
String path = pluginPath;
|
||||
if (appendExtension && !path.EndsWith(NAZARA_DYNLIB_EXTENSION))
|
||||
path += NAZARA_DYNLIB_EXTENSION;
|
||||
|
||||
bool exists = false;
|
||||
if (!File::IsAbsolute(path))
|
||||
{
|
||||
for (const String& dir : s_directories)
|
||||
{
|
||||
path = testPath;
|
||||
exists = true;
|
||||
break;
|
||||
String testPath;
|
||||
testPath.Reserve(dir.GetSize() + path.GetSize() + 10);
|
||||
|
||||
testPath = dir;
|
||||
testPath += NAZARA_DIRECTORY_SEPARATOR;
|
||||
testPath += path;
|
||||
|
||||
if (File::Exists(testPath))
|
||||
{
|
||||
path = testPath;
|
||||
exists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (NzFile::Exists(path))
|
||||
exists = true;
|
||||
else if (File::Exists(path))
|
||||
exists = true;
|
||||
|
||||
if (!exists)
|
||||
{
|
||||
NazaraError("Failed to find plugin file");
|
||||
return false;
|
||||
if (!exists)
|
||||
{
|
||||
NazaraError("Failed to find plugin file");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<DynLib> library(new DynLib);
|
||||
if (!library->Load(path))
|
||||
{
|
||||
NazaraError("Failed to load plugin");
|
||||
return false;
|
||||
}
|
||||
|
||||
PluginLoad func = reinterpret_cast<PluginLoad>(library->GetSymbol("PluginLoad"));
|
||||
if (!func)
|
||||
{
|
||||
NazaraError("Failed to get symbol PluginLoad");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!func())
|
||||
{
|
||||
NazaraError("Plugin failed to load");
|
||||
return false;
|
||||
}
|
||||
|
||||
s_plugins[pluginPath] = library.release();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<NzDynLib> library(new NzDynLib);
|
||||
if (!library->Load(path))
|
||||
void PluginManager::RemoveDirectory(const String& directoryPath)
|
||||
{
|
||||
NazaraError("Failed to load plugin");
|
||||
return false;
|
||||
if (!Initialize())
|
||||
{
|
||||
NazaraError("Failed to initialize PluginManager");
|
||||
return;
|
||||
}
|
||||
|
||||
s_directories.erase(File::AbsolutePath(directoryPath));
|
||||
}
|
||||
|
||||
PluginLoad func = reinterpret_cast<PluginLoad>(library->GetSymbol("NzPluginLoad"));
|
||||
if (!func)
|
||||
void PluginManager::Unmount(Plugin plugin)
|
||||
{
|
||||
NazaraError("Failed to get symbol NzPluginLoad");
|
||||
return false;
|
||||
Unmount(s_pluginFiles[plugin]);
|
||||
}
|
||||
|
||||
if (!func())
|
||||
void PluginManager::Unmount(const String& pluginPath)
|
||||
{
|
||||
NazaraError("Plugin failed to load");
|
||||
return false;
|
||||
}
|
||||
if (!Initialize())
|
||||
{
|
||||
NazaraError("Failed to initialize PluginManager");
|
||||
return;
|
||||
}
|
||||
|
||||
s_plugins[pluginPath] = library.release();
|
||||
auto it = s_plugins.find(pluginPath);
|
||||
if (it == s_plugins.end())
|
||||
{
|
||||
NazaraError("Plugin not loaded");
|
||||
return;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzPluginManager::RemoveDirectory(const NzString& directoryPath)
|
||||
{
|
||||
if (!Initialize())
|
||||
{
|
||||
NazaraError("Failed to initialize PluginManager");
|
||||
return;
|
||||
}
|
||||
|
||||
s_directories.erase(NzFile::AbsolutePath(directoryPath));
|
||||
}
|
||||
|
||||
void NzPluginManager::Unmount(nzPlugin plugin)
|
||||
{
|
||||
Unmount(s_pluginFiles[plugin]);
|
||||
}
|
||||
|
||||
void NzPluginManager::Unmount(const NzString& pluginPath)
|
||||
{
|
||||
if (!Initialize())
|
||||
{
|
||||
NazaraError("Failed to initialize PluginManager");
|
||||
return;
|
||||
}
|
||||
|
||||
auto it = s_plugins.find(pluginPath);
|
||||
if (it == s_plugins.end())
|
||||
{
|
||||
NazaraError("Plugin not loaded");
|
||||
return;
|
||||
}
|
||||
|
||||
PluginUnload func = reinterpret_cast<PluginUnload>(it->second->GetSymbol("NzPluginUnload"));
|
||||
if (func)
|
||||
func();
|
||||
|
||||
it->second->Unload();
|
||||
delete it->second;
|
||||
|
||||
s_plugins.erase(it);
|
||||
}
|
||||
|
||||
void NzPluginManager::Uninitialize()
|
||||
{
|
||||
if (!s_initialized)
|
||||
return;
|
||||
|
||||
s_initialized = false;
|
||||
|
||||
s_directories.clear();
|
||||
|
||||
for (auto& pair : s_plugins)
|
||||
{
|
||||
PluginUnload func = reinterpret_cast<PluginUnload>(pair.second->GetSymbol("NzPluginUnload"));
|
||||
PluginUnload func = reinterpret_cast<PluginUnload>(it->second->GetSymbol("PluginUnload"));
|
||||
if (func)
|
||||
func();
|
||||
|
||||
pair.second->Unload();
|
||||
delete pair.second;
|
||||
it->second->Unload();
|
||||
delete it->second;
|
||||
|
||||
s_plugins.erase(it);
|
||||
}
|
||||
|
||||
s_plugins.clear();
|
||||
}
|
||||
void PluginManager::Uninitialize()
|
||||
{
|
||||
if (!s_initialized)
|
||||
return;
|
||||
|
||||
std::set<NzString> NzPluginManager::s_directories;
|
||||
std::unordered_map<NzString, NzDynLib*> NzPluginManager::s_plugins;
|
||||
bool NzPluginManager::s_initialized = false;
|
||||
s_initialized = false;
|
||||
|
||||
s_directories.clear();
|
||||
|
||||
for (auto& pair : s_plugins)
|
||||
{
|
||||
PluginUnload func = reinterpret_cast<PluginUnload>(pair.second->GetSymbol("PluginUnload"));
|
||||
if (func)
|
||||
func();
|
||||
|
||||
pair.second->Unload();
|
||||
delete pair.second;
|
||||
}
|
||||
|
||||
s_plugins.clear();
|
||||
}
|
||||
|
||||
std::set<String> PluginManager::s_directories;
|
||||
std::unordered_map<String, DynLib*> PluginManager::s_plugins;
|
||||
bool PluginManager::s_initialized = false;
|
||||
}
|
||||
|
||||
@@ -6,112 +6,115 @@
|
||||
#include <Nazara/Core/Config.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
void NzPrimitiveList::AddBox(const NzVector3f& lengths, const NzVector3ui& subdivision, const NzMatrix4f& transformMatrix)
|
||||
namespace Nz
|
||||
{
|
||||
m_primitives.push_back(NzPrimitive::Box(lengths, subdivision, transformMatrix));
|
||||
}
|
||||
|
||||
void NzPrimitiveList::AddBox(const NzVector3f& lengths, const NzVector3ui& subdivision, const NzVector3f& position, const NzQuaternionf& rotation)
|
||||
{
|
||||
m_primitives.push_back(NzPrimitive::Box(lengths, subdivision, position, rotation));
|
||||
}
|
||||
|
||||
void NzPrimitiveList::AddCone(float length, float radius, unsigned int subdivision, const NzMatrix4f& transformMatrix)
|
||||
{
|
||||
m_primitives.push_back(NzPrimitive::Cone(length, radius, subdivision, transformMatrix));
|
||||
}
|
||||
|
||||
void NzPrimitiveList::AddCone(float length, float radius, unsigned int subdivision, const NzVector3f& position, const NzQuaternionf& rotation)
|
||||
{
|
||||
m_primitives.push_back(NzPrimitive::Cone(length, radius, subdivision, position, rotation));
|
||||
}
|
||||
|
||||
void NzPrimitiveList::AddCubicSphere(float size, unsigned int subdivision, const NzMatrix4f& transformMatrix)
|
||||
{
|
||||
m_primitives.push_back(NzPrimitive::CubicSphere(size, subdivision, transformMatrix));
|
||||
}
|
||||
|
||||
void NzPrimitiveList::AddCubicSphere(float size, unsigned int subdivision, const NzVector3f& position, const NzQuaternionf& rotation)
|
||||
{
|
||||
m_primitives.push_back(NzPrimitive::CubicSphere(size, subdivision, position, rotation));
|
||||
}
|
||||
|
||||
void NzPrimitiveList::AddIcoSphere(float size, unsigned int recursionLevel, const NzMatrix4f& transformMatrix)
|
||||
{
|
||||
m_primitives.push_back(NzPrimitive::IcoSphere(size, recursionLevel, transformMatrix));
|
||||
}
|
||||
|
||||
void NzPrimitiveList::AddIcoSphere(float size, unsigned int recursionLevel, const NzVector3f& position, const NzQuaternionf& rotation)
|
||||
{
|
||||
m_primitives.push_back(NzPrimitive::IcoSphere(size, recursionLevel, position, rotation));
|
||||
}
|
||||
|
||||
void NzPrimitiveList::AddPlane(const NzVector2f& size, const NzVector2ui& subdivision, const NzMatrix4f& transformMatrix)
|
||||
{
|
||||
m_primitives.push_back(NzPrimitive::Plane(size, subdivision, transformMatrix));
|
||||
}
|
||||
|
||||
void NzPrimitiveList::AddPlane(const NzVector2f& size, const NzVector2ui& subdivision, const NzPlanef& planeInfo)
|
||||
{
|
||||
m_primitives.push_back(NzPrimitive::Plane(size, subdivision, planeInfo));
|
||||
}
|
||||
|
||||
void NzPrimitiveList::AddPlane(const NzVector2f& size, const NzVector2ui& subdivision, const NzVector3f& position, const NzQuaternionf& rotation)
|
||||
{
|
||||
m_primitives.push_back(NzPrimitive::Plane(size, subdivision, position, rotation));
|
||||
}
|
||||
|
||||
void NzPrimitiveList::AddUVSphere(float size, unsigned int sliceCount, unsigned int stackCount, const NzMatrix4f& transformMatrix)
|
||||
{
|
||||
m_primitives.push_back(NzPrimitive::UVSphere(size, sliceCount, stackCount, transformMatrix));
|
||||
}
|
||||
|
||||
void NzPrimitiveList::AddUVSphere(float size, unsigned int sliceCount, unsigned int stackCount, const NzVector3f& position, const NzQuaternionf& rotation)
|
||||
{
|
||||
m_primitives.push_back(NzPrimitive::UVSphere(size, sliceCount, stackCount, position, rotation));
|
||||
}
|
||||
|
||||
NzPrimitive& NzPrimitiveList::GetPrimitive(unsigned int i)
|
||||
{
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (i >= m_primitives.size())
|
||||
void PrimitiveList::AddBox(const Vector3f& lengths, const Vector3ui& subdivision, const Matrix4f& transformMatrix)
|
||||
{
|
||||
NazaraError("Primitive index out of range (" + NzString::Number(i) + " >= " + NzString::Number(m_primitives.size()) + ')');
|
||||
|
||||
static NzPrimitive dummy;
|
||||
return dummy;
|
||||
m_primitives.push_back(Primitive::Box(lengths, subdivision, transformMatrix));
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_primitives[i];
|
||||
}
|
||||
|
||||
const NzPrimitive& NzPrimitiveList::GetPrimitive(unsigned int i) const
|
||||
{
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (i >= m_primitives.size())
|
||||
void PrimitiveList::AddBox(const Vector3f& lengths, const Vector3ui& subdivision, const Vector3f& position, const Quaternionf& rotation)
|
||||
{
|
||||
NazaraError("Primitive index out of range (" + NzString::Number(i) + " >= " + NzString::Number(m_primitives.size()) + ')');
|
||||
|
||||
static NzPrimitive dummy;
|
||||
return dummy;
|
||||
m_primitives.push_back(Primitive::Box(lengths, subdivision, position, rotation));
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_primitives[i];
|
||||
}
|
||||
void PrimitiveList::AddCone(float length, float radius, unsigned int subdivision, const Matrix4f& transformMatrix)
|
||||
{
|
||||
m_primitives.push_back(Primitive::Cone(length, radius, subdivision, transformMatrix));
|
||||
}
|
||||
|
||||
unsigned int NzPrimitiveList::GetSize() const
|
||||
{
|
||||
return m_primitives.size();
|
||||
}
|
||||
void PrimitiveList::AddCone(float length, float radius, unsigned int subdivision, const Vector3f& position, const Quaternionf& rotation)
|
||||
{
|
||||
m_primitives.push_back(Primitive::Cone(length, radius, subdivision, position, rotation));
|
||||
}
|
||||
|
||||
NzPrimitive& NzPrimitiveList::operator()(unsigned int i)
|
||||
{
|
||||
return GetPrimitive(i);
|
||||
}
|
||||
void PrimitiveList::AddCubicSphere(float size, unsigned int subdivision, const Matrix4f& transformMatrix)
|
||||
{
|
||||
m_primitives.push_back(Primitive::CubicSphere(size, subdivision, transformMatrix));
|
||||
}
|
||||
|
||||
const NzPrimitive& NzPrimitiveList::operator()(unsigned int i) const
|
||||
{
|
||||
return GetPrimitive(i);
|
||||
void PrimitiveList::AddCubicSphere(float size, unsigned int subdivision, const Vector3f& position, const Quaternionf& rotation)
|
||||
{
|
||||
m_primitives.push_back(Primitive::CubicSphere(size, subdivision, position, rotation));
|
||||
}
|
||||
|
||||
void PrimitiveList::AddIcoSphere(float size, unsigned int recursionLevel, const Matrix4f& transformMatrix)
|
||||
{
|
||||
m_primitives.push_back(Primitive::IcoSphere(size, recursionLevel, transformMatrix));
|
||||
}
|
||||
|
||||
void PrimitiveList::AddIcoSphere(float size, unsigned int recursionLevel, const Vector3f& position, const Quaternionf& rotation)
|
||||
{
|
||||
m_primitives.push_back(Primitive::IcoSphere(size, recursionLevel, position, rotation));
|
||||
}
|
||||
|
||||
void PrimitiveList::AddPlane(const Vector2f& size, const Vector2ui& subdivision, const Matrix4f& transformMatrix)
|
||||
{
|
||||
m_primitives.push_back(Primitive::Plane(size, subdivision, transformMatrix));
|
||||
}
|
||||
|
||||
void PrimitiveList::AddPlane(const Vector2f& size, const Vector2ui& subdivision, const Planef& planeInfo)
|
||||
{
|
||||
m_primitives.push_back(Primitive::Plane(size, subdivision, planeInfo));
|
||||
}
|
||||
|
||||
void PrimitiveList::AddPlane(const Vector2f& size, const Vector2ui& subdivision, const Vector3f& position, const Quaternionf& rotation)
|
||||
{
|
||||
m_primitives.push_back(Primitive::Plane(size, subdivision, position, rotation));
|
||||
}
|
||||
|
||||
void PrimitiveList::AddUVSphere(float size, unsigned int sliceCount, unsigned int stackCount, const Matrix4f& transformMatrix)
|
||||
{
|
||||
m_primitives.push_back(Primitive::UVSphere(size, sliceCount, stackCount, transformMatrix));
|
||||
}
|
||||
|
||||
void PrimitiveList::AddUVSphere(float size, unsigned int sliceCount, unsigned int stackCount, const Vector3f& position, const Quaternionf& rotation)
|
||||
{
|
||||
m_primitives.push_back(Primitive::UVSphere(size, sliceCount, stackCount, position, rotation));
|
||||
}
|
||||
|
||||
Primitive& PrimitiveList::GetPrimitive(unsigned int i)
|
||||
{
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (i >= m_primitives.size())
|
||||
{
|
||||
NazaraError("Primitive index out of range (" + String::Number(i) + " >= " + String::Number(m_primitives.size()) + ')');
|
||||
|
||||
static Primitive dummy;
|
||||
return dummy;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_primitives[i];
|
||||
}
|
||||
|
||||
const Primitive& PrimitiveList::GetPrimitive(unsigned int i) const
|
||||
{
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (i >= m_primitives.size())
|
||||
{
|
||||
NazaraError("Primitive index out of range (" + String::Number(i) + " >= " + String::Number(m_primitives.size()) + ')');
|
||||
|
||||
static Primitive dummy;
|
||||
return dummy;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_primitives[i];
|
||||
}
|
||||
|
||||
unsigned int PrimitiveList::GetSize() const
|
||||
{
|
||||
return m_primitives.size();
|
||||
}
|
||||
|
||||
Primitive& PrimitiveList::operator()(unsigned int i)
|
||||
{
|
||||
return GetPrimitive(i);
|
||||
}
|
||||
|
||||
const Primitive& PrimitiveList::operator()(unsigned int i) const
|
||||
{
|
||||
return GetPrimitive(i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,66 +14,68 @@
|
||||
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzRefCounted::NzRefCounted(bool persistent) :
|
||||
m_persistent(persistent),
|
||||
m_referenceCount(0)
|
||||
namespace Nz
|
||||
{
|
||||
}
|
||||
|
||||
NzRefCounted::~NzRefCounted()
|
||||
{
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (m_referenceCount > 0)
|
||||
NazaraWarning("Resource destroyed while still referenced " + NzString::Number(m_referenceCount) + " time(s)");
|
||||
#endif
|
||||
}
|
||||
|
||||
void NzRefCounted::AddReference() const
|
||||
{
|
||||
m_referenceCount++;
|
||||
}
|
||||
|
||||
unsigned int NzRefCounted::GetReferenceCount() const
|
||||
{
|
||||
return m_referenceCount;
|
||||
}
|
||||
|
||||
bool NzRefCounted::IsPersistent() const
|
||||
{
|
||||
return m_persistent;
|
||||
}
|
||||
|
||||
bool NzRefCounted::RemoveReference() const
|
||||
{
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (m_referenceCount == 0)
|
||||
RefCounted::RefCounted(bool persistent) :
|
||||
m_persistent(persistent),
|
||||
m_referenceCount(0)
|
||||
{
|
||||
NazaraError("Impossible to remove reference (Ref. counter is already 0)");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (--m_referenceCount == 0 && !m_persistent)
|
||||
RefCounted::~RefCounted()
|
||||
{
|
||||
delete this; // Suicide
|
||||
|
||||
return true;
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (m_referenceCount > 0)
|
||||
NazaraWarning("Resource destroyed while still referenced " + String::Number(m_referenceCount) + " time(s)");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NzRefCounted::SetPersistent(bool persistent, bool checkReferenceCount)
|
||||
{
|
||||
m_persistent = persistent;
|
||||
|
||||
if (checkReferenceCount && !persistent && m_referenceCount == 0)
|
||||
void RefCounted::AddReference() const
|
||||
{
|
||||
delete this;
|
||||
|
||||
return true;
|
||||
m_referenceCount++;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int RefCounted::GetReferenceCount() const
|
||||
{
|
||||
return m_referenceCount;
|
||||
}
|
||||
|
||||
bool RefCounted::IsPersistent() const
|
||||
{
|
||||
return m_persistent;
|
||||
}
|
||||
|
||||
bool RefCounted::RemoveReference() const
|
||||
{
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (m_referenceCount == 0)
|
||||
{
|
||||
NazaraError("Impossible to remove reference (Ref. counter is already 0)");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (--m_referenceCount == 0 && !m_persistent)
|
||||
{
|
||||
delete this; // Suicide
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RefCounted::SetPersistent(bool persistent, bool checkReferenceCount)
|
||||
{
|
||||
m_persistent = persistent;
|
||||
|
||||
if (checkReferenceCount && !persistent && m_referenceCount == 0)
|
||||
{
|
||||
delete this;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,14 +5,17 @@
|
||||
#include <Nazara/Core/Resource.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzResource::~NzResource() = default;
|
||||
|
||||
const NzString& NzResource::GetFilePath() const
|
||||
namespace Nz
|
||||
{
|
||||
return m_filePath;
|
||||
}
|
||||
Resource::~Resource() = default;
|
||||
|
||||
void NzResource::SetFilePath(const NzString& filePath)
|
||||
{
|
||||
m_filePath = filePath;
|
||||
const String& Resource::GetFilePath() const
|
||||
{
|
||||
return m_filePath;
|
||||
}
|
||||
|
||||
void Resource::SetFilePath(const String& filePath)
|
||||
{
|
||||
m_filePath = filePath;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,32 +14,35 @@
|
||||
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzSemaphore::NzSemaphore(unsigned int count)
|
||||
namespace Nz
|
||||
{
|
||||
m_impl = new NzSemaphoreImpl(count);
|
||||
}
|
||||
Semaphore::Semaphore(unsigned int count)
|
||||
{
|
||||
m_impl = new SemaphoreImpl(count);
|
||||
}
|
||||
|
||||
NzSemaphore::~NzSemaphore()
|
||||
{
|
||||
delete m_impl;
|
||||
}
|
||||
Semaphore::~Semaphore()
|
||||
{
|
||||
delete m_impl;
|
||||
}
|
||||
|
||||
unsigned int NzSemaphore::GetCount() const
|
||||
{
|
||||
return m_impl->GetCount();
|
||||
}
|
||||
unsigned int Semaphore::GetCount() const
|
||||
{
|
||||
return m_impl->GetCount();
|
||||
}
|
||||
|
||||
void NzSemaphore::Post()
|
||||
{
|
||||
m_impl->Post();
|
||||
}
|
||||
void Semaphore::Post()
|
||||
{
|
||||
m_impl->Post();
|
||||
}
|
||||
|
||||
void NzSemaphore::Wait()
|
||||
{
|
||||
m_impl->Wait();
|
||||
}
|
||||
void Semaphore::Wait()
|
||||
{
|
||||
m_impl->Wait();
|
||||
}
|
||||
|
||||
bool NzSemaphore::Wait(nzUInt32 timeout)
|
||||
{
|
||||
return m_impl->Wait(timeout);
|
||||
bool Semaphore::Wait(UInt32 timeout)
|
||||
{
|
||||
return m_impl->Wait(timeout);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,24 +5,27 @@
|
||||
#include <Nazara/Core/Stream.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzStream::~NzStream() = default;
|
||||
|
||||
NzString NzStream::GetDirectory() const
|
||||
namespace Nz
|
||||
{
|
||||
return NzString();
|
||||
}
|
||||
Stream::~Stream() = default;
|
||||
|
||||
NzString NzStream::GetPath() const
|
||||
{
|
||||
return NzString();
|
||||
}
|
||||
String Stream::GetDirectory() const
|
||||
{
|
||||
return String();
|
||||
}
|
||||
|
||||
unsigned int NzStream::GetStreamOptions() const
|
||||
{
|
||||
return m_streamOptions;
|
||||
}
|
||||
String Stream::GetPath() const
|
||||
{
|
||||
return String();
|
||||
}
|
||||
|
||||
void NzStream::SetStreamOptions(unsigned int options)
|
||||
{
|
||||
m_streamOptions = options;
|
||||
unsigned int Stream::GetStreamOptions() const
|
||||
{
|
||||
return m_streamOptions;
|
||||
}
|
||||
|
||||
void Stream::SetStreamOptions(unsigned int options)
|
||||
{
|
||||
m_streamOptions = options;
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,173 +5,176 @@
|
||||
#include <Nazara/Core/StringStream.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzStringStream::NzStringStream() :
|
||||
m_bufferSize(0)
|
||||
namespace Nz
|
||||
{
|
||||
}
|
||||
|
||||
NzStringStream::NzStringStream(const NzString& str) :
|
||||
m_bufferSize(str.GetSize())
|
||||
{
|
||||
m_strings.push_back(str);
|
||||
}
|
||||
|
||||
NzString NzStringStream::ToString() const
|
||||
{
|
||||
NzString string;
|
||||
string.Reserve(m_bufferSize);
|
||||
|
||||
for (const NzString& str : m_strings)
|
||||
string += str;
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
NzStringStream& NzStringStream::operator<<(bool boolean)
|
||||
{
|
||||
m_strings.push_back(NzString::Boolean(boolean));
|
||||
m_bufferSize += m_strings.back().GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzStringStream& NzStringStream::operator<<(short number)
|
||||
{
|
||||
m_strings.push_back(NzString::Number(number));
|
||||
m_bufferSize += m_strings.back().GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzStringStream& NzStringStream::operator<<(unsigned short number)
|
||||
{
|
||||
m_strings.push_back(NzString::Number(number));
|
||||
m_bufferSize += m_strings.back().GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzStringStream& NzStringStream::operator<<(int number)
|
||||
{
|
||||
m_strings.push_back(NzString::Number(number));
|
||||
m_bufferSize += m_strings.back().GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzStringStream& NzStringStream::operator<<(unsigned int number)
|
||||
{
|
||||
m_strings.push_back(NzString::Number(number));
|
||||
m_bufferSize += m_strings.back().GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzStringStream& NzStringStream::operator<<(long number)
|
||||
{
|
||||
m_strings.push_back(NzString::Number(number));
|
||||
m_bufferSize += m_strings.back().GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzStringStream& NzStringStream::operator<<(unsigned long number)
|
||||
{
|
||||
m_strings.push_back(NzString::Number(number));
|
||||
m_bufferSize += m_strings.back().GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzStringStream& NzStringStream::operator<<(long long number)
|
||||
{
|
||||
m_strings.push_back(NzString::Number(number));
|
||||
m_bufferSize += m_strings.back().GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzStringStream& NzStringStream::operator<<(unsigned long long number)
|
||||
{
|
||||
m_strings.push_back(NzString::Number(number));
|
||||
m_bufferSize += m_strings.back().GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzStringStream& NzStringStream::operator<<(float number)
|
||||
{
|
||||
m_strings.push_back(NzString::Number(number));
|
||||
m_bufferSize += m_strings.back().GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzStringStream& NzStringStream::operator<<(double number)
|
||||
{
|
||||
m_strings.push_back(NzString::Number(number));
|
||||
m_bufferSize += m_strings.back().GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzStringStream& NzStringStream::operator<<(long double number)
|
||||
{
|
||||
m_strings.push_back(NzString::Number(number));
|
||||
m_bufferSize += m_strings.back().GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzStringStream& NzStringStream::operator<<(char character)
|
||||
{
|
||||
m_strings.push_back(NzString(character));
|
||||
m_bufferSize++;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzStringStream& NzStringStream::operator<<(unsigned char character)
|
||||
{
|
||||
m_strings.push_back(NzString(static_cast<char>(character)));
|
||||
m_bufferSize++;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzStringStream& NzStringStream::operator<<(const char* string)
|
||||
{
|
||||
m_strings.push_back(string);
|
||||
m_bufferSize += m_strings.back().GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzStringStream& NzStringStream::operator<<(const std::string& string)
|
||||
{
|
||||
m_strings.push_back(string);
|
||||
m_bufferSize += string.size();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzStringStream& NzStringStream::operator<<(const NzString& string)
|
||||
{
|
||||
m_strings.push_back(string);
|
||||
m_bufferSize += string.GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzStringStream& NzStringStream::operator<<(const void* ptr)
|
||||
{
|
||||
m_strings.push_back(NzString::Pointer(ptr));
|
||||
m_bufferSize += m_strings.back().GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
NzStringStream::operator NzString() const
|
||||
{
|
||||
return ToString();
|
||||
StringStream::StringStream() :
|
||||
m_bufferSize(0)
|
||||
{
|
||||
}
|
||||
|
||||
StringStream::StringStream(const String& str) :
|
||||
m_bufferSize(str.GetSize())
|
||||
{
|
||||
m_strings.push_back(str);
|
||||
}
|
||||
|
||||
String StringStream::ToString() const
|
||||
{
|
||||
String string;
|
||||
string.Reserve(m_bufferSize);
|
||||
|
||||
for (const String& str : m_strings)
|
||||
string += str;
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
StringStream& StringStream::operator<<(bool boolean)
|
||||
{
|
||||
m_strings.push_back(String::Boolean(boolean));
|
||||
m_bufferSize += m_strings.back().GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringStream& StringStream::operator<<(short number)
|
||||
{
|
||||
m_strings.push_back(String::Number(number));
|
||||
m_bufferSize += m_strings.back().GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringStream& StringStream::operator<<(unsigned short number)
|
||||
{
|
||||
m_strings.push_back(String::Number(number));
|
||||
m_bufferSize += m_strings.back().GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringStream& StringStream::operator<<(int number)
|
||||
{
|
||||
m_strings.push_back(String::Number(number));
|
||||
m_bufferSize += m_strings.back().GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringStream& StringStream::operator<<(unsigned int number)
|
||||
{
|
||||
m_strings.push_back(String::Number(number));
|
||||
m_bufferSize += m_strings.back().GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringStream& StringStream::operator<<(long number)
|
||||
{
|
||||
m_strings.push_back(String::Number(number));
|
||||
m_bufferSize += m_strings.back().GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringStream& StringStream::operator<<(unsigned long number)
|
||||
{
|
||||
m_strings.push_back(String::Number(number));
|
||||
m_bufferSize += m_strings.back().GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringStream& StringStream::operator<<(long long number)
|
||||
{
|
||||
m_strings.push_back(String::Number(number));
|
||||
m_bufferSize += m_strings.back().GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringStream& StringStream::operator<<(unsigned long long number)
|
||||
{
|
||||
m_strings.push_back(String::Number(number));
|
||||
m_bufferSize += m_strings.back().GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringStream& StringStream::operator<<(float number)
|
||||
{
|
||||
m_strings.push_back(String::Number(number));
|
||||
m_bufferSize += m_strings.back().GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringStream& StringStream::operator<<(double number)
|
||||
{
|
||||
m_strings.push_back(String::Number(number));
|
||||
m_bufferSize += m_strings.back().GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringStream& StringStream::operator<<(long double number)
|
||||
{
|
||||
m_strings.push_back(String::Number(number));
|
||||
m_bufferSize += m_strings.back().GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringStream& StringStream::operator<<(char character)
|
||||
{
|
||||
m_strings.push_back(String(character));
|
||||
m_bufferSize++;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringStream& StringStream::operator<<(unsigned char character)
|
||||
{
|
||||
m_strings.push_back(String(static_cast<char>(character)));
|
||||
m_bufferSize++;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringStream& StringStream::operator<<(const char* string)
|
||||
{
|
||||
m_strings.push_back(string);
|
||||
m_bufferSize += m_strings.back().GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringStream& StringStream::operator<<(const std::string& string)
|
||||
{
|
||||
m_strings.push_back(string);
|
||||
m_bufferSize += string.size();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringStream& StringStream::operator<<(const String& string)
|
||||
{
|
||||
m_strings.push_back(string);
|
||||
m_bufferSize += string.GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringStream& StringStream::operator<<(const void* ptr)
|
||||
{
|
||||
m_strings.push_back(String::Pointer(ptr));
|
||||
m_bufferSize += m_strings.back().GetSize();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
StringStream::operator String() const
|
||||
{
|
||||
return ToString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,74 +16,77 @@
|
||||
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
namespace
|
||||
namespace Nz
|
||||
{
|
||||
std::vector<NzFunctor*> s_pendingWorks;
|
||||
unsigned int s_workerCount = 0;
|
||||
}
|
||||
|
||||
unsigned int NzTaskScheduler::GetWorkerCount()
|
||||
{
|
||||
return (s_workerCount > 0) ? s_workerCount : NzHardwareInfo::GetProcessorCount();
|
||||
}
|
||||
|
||||
bool NzTaskScheduler::Initialize()
|
||||
{
|
||||
return NzTaskSchedulerImpl::Initialize(GetWorkerCount());
|
||||
}
|
||||
|
||||
void NzTaskScheduler::Run()
|
||||
{
|
||||
if (!Initialize())
|
||||
namespace
|
||||
{
|
||||
NazaraError("Failed to initialize Task Scheduler");
|
||||
return;
|
||||
std::vector<Functor*> s_pendingWorks;
|
||||
unsigned int s_workerCount = 0;
|
||||
}
|
||||
|
||||
if (!s_pendingWorks.empty())
|
||||
unsigned int TaskScheduler::GetWorkerCount()
|
||||
{
|
||||
NzTaskSchedulerImpl::Run(&s_pendingWorks[0], s_pendingWorks.size());
|
||||
s_pendingWorks.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void NzTaskScheduler::SetWorkerCount(unsigned int workerCount)
|
||||
{
|
||||
#ifdef NAZARA_CORE_SAFE
|
||||
if (NzTaskSchedulerImpl::IsInitialized())
|
||||
{
|
||||
NazaraError("Worker count cannot be set while initialized");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
s_workerCount = workerCount;
|
||||
}
|
||||
|
||||
void NzTaskScheduler::Uninitialize()
|
||||
{
|
||||
if (NzTaskSchedulerImpl::IsInitialized())
|
||||
NzTaskSchedulerImpl::Uninitialize();
|
||||
}
|
||||
|
||||
void NzTaskScheduler::WaitForTasks()
|
||||
{
|
||||
if (!Initialize())
|
||||
{
|
||||
NazaraError("Failed to initialize Task Scheduler");
|
||||
return;
|
||||
return (s_workerCount > 0) ? s_workerCount : HardwareInfo::GetProcessorCount();
|
||||
}
|
||||
|
||||
NzTaskSchedulerImpl::WaitForTasks();
|
||||
}
|
||||
|
||||
void NzTaskScheduler::AddTaskFunctor(NzFunctor* taskFunctor)
|
||||
{
|
||||
if (!Initialize())
|
||||
bool TaskScheduler::Initialize()
|
||||
{
|
||||
NazaraError("Failed to initialize Task Scheduler");
|
||||
return;
|
||||
return TaskSchedulerImpl::Initialize(GetWorkerCount());
|
||||
}
|
||||
|
||||
s_pendingWorks.push_back(taskFunctor);
|
||||
void TaskScheduler::Run()
|
||||
{
|
||||
if (!Initialize())
|
||||
{
|
||||
NazaraError("Failed to initialize Task Scheduler");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!s_pendingWorks.empty())
|
||||
{
|
||||
TaskSchedulerImpl::Run(&s_pendingWorks[0], s_pendingWorks.size());
|
||||
s_pendingWorks.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void TaskScheduler::SetWorkerCount(unsigned int workerCount)
|
||||
{
|
||||
#ifdef NAZARA_CORE_SAFE
|
||||
if (TaskSchedulerImpl::IsInitialized())
|
||||
{
|
||||
NazaraError("Worker count cannot be set while initialized");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
s_workerCount = workerCount;
|
||||
}
|
||||
|
||||
void TaskScheduler::Uninitialize()
|
||||
{
|
||||
if (TaskSchedulerImpl::IsInitialized())
|
||||
TaskSchedulerImpl::Uninitialize();
|
||||
}
|
||||
|
||||
void TaskScheduler::WaitForTasks()
|
||||
{
|
||||
if (!Initialize())
|
||||
{
|
||||
NazaraError("Failed to initialize Task Scheduler");
|
||||
return;
|
||||
}
|
||||
|
||||
TaskSchedulerImpl::WaitForTasks();
|
||||
}
|
||||
|
||||
void TaskScheduler::AddTaskFunctor(Functor* taskFunctor)
|
||||
{
|
||||
if (!Initialize())
|
||||
{
|
||||
NazaraError("Failed to initialize Task Scheduler");
|
||||
return;
|
||||
}
|
||||
|
||||
s_pendingWorks.push_back(taskFunctor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,130 +19,133 @@
|
||||
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzThread::NzThread() :
|
||||
m_impl(nullptr)
|
||||
namespace Nz
|
||||
{
|
||||
}
|
||||
|
||||
NzThread::NzThread(NzThread&& other) noexcept :
|
||||
m_impl(other.m_impl)
|
||||
{
|
||||
other.m_impl = nullptr;
|
||||
}
|
||||
|
||||
NzThread::~NzThread()
|
||||
{
|
||||
if (m_impl)
|
||||
Thread::Thread() :
|
||||
m_impl(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
Thread::Thread(Thread&& other) noexcept :
|
||||
m_impl(other.m_impl)
|
||||
{
|
||||
other.m_impl = nullptr;
|
||||
}
|
||||
|
||||
Thread::~Thread()
|
||||
{
|
||||
if (m_impl)
|
||||
{
|
||||
m_impl->Join();
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void Thread::Detach()
|
||||
{
|
||||
if (m_impl)
|
||||
{
|
||||
m_impl->Detach();
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Thread::Id Thread::GetId() const
|
||||
{
|
||||
return Thread::Id(m_impl);
|
||||
}
|
||||
|
||||
bool Thread::IsJoinable() const
|
||||
{
|
||||
return m_impl != nullptr;
|
||||
}
|
||||
|
||||
void Thread::Join()
|
||||
{
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("This thread is not joinable");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
m_impl->Join();
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void NzThread::Detach()
|
||||
{
|
||||
if (m_impl)
|
||||
Thread& Thread::operator=(Thread&& thread)
|
||||
{
|
||||
m_impl->Detach();
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (m_impl)
|
||||
{
|
||||
NazaraError("This thread cannot be joined");
|
||||
std::terminate();
|
||||
}
|
||||
#endif
|
||||
|
||||
std::swap(m_impl, thread.m_impl);
|
||||
return *this;
|
||||
}
|
||||
|
||||
unsigned int Thread::HardwareConcurrency()
|
||||
{
|
||||
return HardwareInfo::GetProcessorCount();
|
||||
}
|
||||
|
||||
void Thread::Sleep(UInt32 milliseconds)
|
||||
{
|
||||
ThreadImpl::Sleep(milliseconds);
|
||||
}
|
||||
|
||||
void Thread::CreateImpl(Functor* functor)
|
||||
{
|
||||
m_impl = new ThreadImpl(functor);
|
||||
}
|
||||
|
||||
/*********************************Thread::Id********************************/
|
||||
|
||||
Thread::Id::Id(ThreadImpl* thread) :
|
||||
m_id(thread)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator==(const Thread::Id& lhs, const Thread::Id& rhs)
|
||||
{
|
||||
return lhs.m_id == rhs.m_id;
|
||||
}
|
||||
|
||||
bool operator!=(const Thread::Id& lhs, const Thread::Id& rhs)
|
||||
{
|
||||
return lhs.m_id != rhs.m_id;
|
||||
}
|
||||
|
||||
bool operator<(const Thread::Id& lhs, const Thread::Id& rhs)
|
||||
{
|
||||
return lhs.m_id < rhs.m_id;
|
||||
}
|
||||
|
||||
bool operator<=(const Thread::Id& lhs, const Thread::Id& rhs)
|
||||
{
|
||||
return lhs.m_id <= rhs.m_id;
|
||||
}
|
||||
|
||||
bool operator>(const Thread::Id& lhs, const Thread::Id& rhs)
|
||||
{
|
||||
return lhs.m_id > rhs.m_id;
|
||||
}
|
||||
|
||||
bool operator>=(const Thread::Id& lhs, const Thread::Id& rhs)
|
||||
{
|
||||
return lhs.m_id >= rhs.m_id;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& o, const Nz::Thread::Id& id)
|
||||
{
|
||||
o << id.m_id;
|
||||
return o;
|
||||
}
|
||||
}
|
||||
|
||||
NzThread::Id NzThread::GetId() const
|
||||
{
|
||||
return NzThread::Id(m_impl);
|
||||
}
|
||||
|
||||
bool NzThread::IsJoinable() const
|
||||
{
|
||||
return m_impl != nullptr;
|
||||
}
|
||||
|
||||
void NzThread::Join()
|
||||
{
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("This thread is not joinable");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
m_impl->Join();
|
||||
delete m_impl;
|
||||
m_impl = nullptr;
|
||||
}
|
||||
|
||||
NzThread& NzThread::operator=(NzThread&& thread)
|
||||
{
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (m_impl)
|
||||
{
|
||||
NazaraError("This thread cannot be joined");
|
||||
std::terminate();
|
||||
}
|
||||
#endif
|
||||
|
||||
std::swap(m_impl, thread.m_impl);
|
||||
return *this;
|
||||
}
|
||||
|
||||
unsigned int NzThread::HardwareConcurrency()
|
||||
{
|
||||
return NzHardwareInfo::GetProcessorCount();
|
||||
}
|
||||
|
||||
void NzThread::Sleep(nzUInt32 milliseconds)
|
||||
{
|
||||
NzThreadImpl::Sleep(milliseconds);
|
||||
}
|
||||
|
||||
void NzThread::CreateImpl(NzFunctor* functor)
|
||||
{
|
||||
m_impl = new NzThreadImpl(functor);
|
||||
}
|
||||
|
||||
/*********************************NzThread::Id********************************/
|
||||
|
||||
bool operator==(const NzThread::Id& lhs, const NzThread::Id& rhs)
|
||||
{
|
||||
return lhs.m_id == rhs.m_id;
|
||||
}
|
||||
|
||||
bool operator!=(const NzThread::Id& lhs, const NzThread::Id& rhs)
|
||||
{
|
||||
return lhs.m_id != rhs.m_id;
|
||||
}
|
||||
|
||||
bool operator<(const NzThread::Id& lhs, const NzThread::Id& rhs)
|
||||
{
|
||||
return lhs.m_id < rhs.m_id;
|
||||
}
|
||||
|
||||
bool operator<=(const NzThread::Id& lhs, const NzThread::Id& rhs)
|
||||
{
|
||||
return lhs.m_id <= rhs.m_id;
|
||||
}
|
||||
|
||||
bool operator>(const NzThread::Id& lhs, const NzThread::Id& rhs)
|
||||
{
|
||||
return lhs.m_id > rhs.m_id;
|
||||
}
|
||||
|
||||
bool operator>=(const NzThread::Id& lhs, const NzThread::Id& rhs)
|
||||
{
|
||||
return lhs.m_id >= rhs.m_id;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& o, const NzThread::Id& id)
|
||||
{
|
||||
o << id.m_id;
|
||||
return o;
|
||||
}
|
||||
|
||||
NzThread::Id::Id(NzThreadImpl* thread) :
|
||||
m_id(thread)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -7,359 +7,366 @@
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
#if NAZARA_CORE_INCLUDE_UNICODEDATA
|
||||
struct Character
|
||||
namespace Nz
|
||||
{
|
||||
nzUInt16 category; // Le type du caractère
|
||||
nzUInt8 direction; // Le sens de lecure du caractère
|
||||
nzUInt32 lowerCase; // Le caractère correspondant en minuscule
|
||||
nzUInt32 titleCase; // Le caractère correspondant en titre
|
||||
nzUInt32 upperCase; // Le caractère correspondant en majuscule
|
||||
};
|
||||
struct Character
|
||||
{
|
||||
UInt16 category; // Le type du caractère
|
||||
UInt8 direction; // Le sens de lecure du caractère
|
||||
UInt32 lowerCase; // Le caractère correspondant en minuscule
|
||||
UInt32 titleCase; // Le caractère correspondant en titre
|
||||
UInt32 upperCase; // Le caractère correspondant en majuscule
|
||||
};
|
||||
}
|
||||
|
||||
#include <Nazara/Core/UnicodeData.hpp>
|
||||
|
||||
#else // Implémentation supportant la table ASCII
|
||||
|
||||
NzUnicode::Category NzUnicode::GetCategory(char32_t character)
|
||||
namespace Nz
|
||||
{
|
||||
switch (character)
|
||||
Unicode::Category Unicode::GetCategory(char32_t character)
|
||||
{
|
||||
case '\x00':
|
||||
case '\x01':
|
||||
case '\x02':
|
||||
case '\x03':
|
||||
case '\x04':
|
||||
case '\x05':
|
||||
case '\x06':
|
||||
case '\x07':
|
||||
case '\x08':
|
||||
case '\x09':
|
||||
case '\x0A':
|
||||
case '\x0B':
|
||||
case '\x0C':
|
||||
case '\x0D':
|
||||
case '\x0E':
|
||||
case '\x0F':
|
||||
case '\x10':
|
||||
case '\x11':
|
||||
case '\x12':
|
||||
case '\x13':
|
||||
case '\x14':
|
||||
case '\x15':
|
||||
case '\x16':
|
||||
case '\x17':
|
||||
case '\x18':
|
||||
case '\x19':
|
||||
case '\x1A':
|
||||
case '\x1B':
|
||||
case '\x1C':
|
||||
case '\x1D':
|
||||
case '\x1E':
|
||||
case '\x1F':
|
||||
case '\x7F':
|
||||
return Category_Other_Control;
|
||||
switch (character)
|
||||
{
|
||||
case '\x00':
|
||||
case '\x01':
|
||||
case '\x02':
|
||||
case '\x03':
|
||||
case '\x04':
|
||||
case '\x05':
|
||||
case '\x06':
|
||||
case '\x07':
|
||||
case '\x08':
|
||||
case '\x09':
|
||||
case '\x0A':
|
||||
case '\x0B':
|
||||
case '\x0C':
|
||||
case '\x0D':
|
||||
case '\x0E':
|
||||
case '\x0F':
|
||||
case '\x10':
|
||||
case '\x11':
|
||||
case '\x12':
|
||||
case '\x13':
|
||||
case '\x14':
|
||||
case '\x15':
|
||||
case '\x16':
|
||||
case '\x17':
|
||||
case '\x18':
|
||||
case '\x19':
|
||||
case '\x1A':
|
||||
case '\x1B':
|
||||
case '\x1C':
|
||||
case '\x1D':
|
||||
case '\x1E':
|
||||
case '\x1F':
|
||||
case '\x7F':
|
||||
return Category_Other_Control;
|
||||
|
||||
case ' ':
|
||||
return Category_Separator_Space;
|
||||
case ' ':
|
||||
return Category_Separator_Space;
|
||||
|
||||
case '!':
|
||||
case '"':
|
||||
case '#':
|
||||
case '$':
|
||||
case '%':
|
||||
case '&':
|
||||
case '\'':
|
||||
case '*':
|
||||
case ',':
|
||||
case '.':
|
||||
case '/':
|
||||
case ':':
|
||||
case ';':
|
||||
case '?':
|
||||
case '@':
|
||||
case '\\':
|
||||
return Category_Punctuation_Other;
|
||||
case '!':
|
||||
case '"':
|
||||
case '#':
|
||||
case '$':
|
||||
case '%':
|
||||
case '&':
|
||||
case '\'':
|
||||
case '*':
|
||||
case ',':
|
||||
case '.':
|
||||
case '/':
|
||||
case ':':
|
||||
case ';':
|
||||
case '?':
|
||||
case '@':
|
||||
case '\\':
|
||||
return Category_Punctuation_Other;
|
||||
|
||||
case '(':
|
||||
case '[':
|
||||
case '{':
|
||||
return Category_Punctuation_Open;
|
||||
case '(':
|
||||
case '[':
|
||||
case '{':
|
||||
return Category_Punctuation_Open;
|
||||
|
||||
case ')':
|
||||
case '}':
|
||||
case ']':
|
||||
return Category_Punctuation_Close;
|
||||
case ')':
|
||||
case '}':
|
||||
case ']':
|
||||
return Category_Punctuation_Close;
|
||||
|
||||
case '+':
|
||||
case '<':
|
||||
case '=':
|
||||
case '>':
|
||||
case '|':
|
||||
case '~':
|
||||
return Category_Symbol_Math;
|
||||
case '+':
|
||||
case '<':
|
||||
case '=':
|
||||
case '>':
|
||||
case '|':
|
||||
case '~':
|
||||
return Category_Symbol_Math;
|
||||
|
||||
case '-':
|
||||
return Category_Punctuation_Dash;
|
||||
case '-':
|
||||
return Category_Punctuation_Dash;
|
||||
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
return Category_Number_DecimalDigit;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
return Category_Number_DecimalDigit;
|
||||
|
||||
case 'A':
|
||||
case 'B':
|
||||
case 'C':
|
||||
case 'D':
|
||||
case 'E':
|
||||
case 'F':
|
||||
case 'G':
|
||||
case 'H':
|
||||
case 'I':
|
||||
case 'J':
|
||||
case 'K':
|
||||
case 'L':
|
||||
case 'M':
|
||||
case 'N':
|
||||
case 'O':
|
||||
case 'P':
|
||||
case 'Q':
|
||||
case 'R':
|
||||
case 'S':
|
||||
case 'T':
|
||||
case 'U':
|
||||
case 'V':
|
||||
case 'W':
|
||||
case 'X':
|
||||
case 'Y':
|
||||
case 'Z':
|
||||
return Category_Number_DecimalDigit;
|
||||
case 'A':
|
||||
case 'B':
|
||||
case 'C':
|
||||
case 'D':
|
||||
case 'E':
|
||||
case 'F':
|
||||
case 'G':
|
||||
case 'H':
|
||||
case 'I':
|
||||
case 'J':
|
||||
case 'K':
|
||||
case 'L':
|
||||
case 'M':
|
||||
case 'N':
|
||||
case 'O':
|
||||
case 'P':
|
||||
case 'Q':
|
||||
case 'R':
|
||||
case 'S':
|
||||
case 'T':
|
||||
case 'U':
|
||||
case 'V':
|
||||
case 'W':
|
||||
case 'X':
|
||||
case 'Y':
|
||||
case 'Z':
|
||||
return Category_Number_DecimalDigit;
|
||||
|
||||
case '_':
|
||||
return Category_Punctuation_Connector;
|
||||
case '_':
|
||||
return Category_Punctuation_Connector;
|
||||
|
||||
case '^':
|
||||
case '`':
|
||||
return Category_Symbol_Modifier;
|
||||
case '^':
|
||||
case '`':
|
||||
return Category_Symbol_Modifier;
|
||||
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f':
|
||||
case 'g':
|
||||
case 'h':
|
||||
case 'i':
|
||||
case 'j':
|
||||
case 'k':
|
||||
case 'l':
|
||||
case 'm':
|
||||
case 'n':
|
||||
case 'o':
|
||||
case 'p':
|
||||
case 'q':
|
||||
case 'r':
|
||||
case 's':
|
||||
case 't':
|
||||
case 'u':
|
||||
case 'v':
|
||||
case 'w':
|
||||
case 'x':
|
||||
case 'y':
|
||||
case 'z':
|
||||
return Category_Number_DecimalDigit;
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f':
|
||||
case 'g':
|
||||
case 'h':
|
||||
case 'i':
|
||||
case 'j':
|
||||
case 'k':
|
||||
case 'l':
|
||||
case 'm':
|
||||
case 'n':
|
||||
case 'o':
|
||||
case 'p':
|
||||
case 'q':
|
||||
case 'r':
|
||||
case 's':
|
||||
case 't':
|
||||
case 'u':
|
||||
case 'v':
|
||||
case 'w':
|
||||
case 'x':
|
||||
case 'y':
|
||||
case 'z':
|
||||
return Category_Number_DecimalDigit;
|
||||
|
||||
default:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return Category_NoCategory;
|
||||
}
|
||||
|
||||
return Category_NoCategory;
|
||||
}
|
||||
|
||||
NzUnicode::Direction NzUnicode::GetDirection(char32_t character)
|
||||
{
|
||||
switch (character)
|
||||
Unicode::Direction Unicode::GetDirection(char32_t character)
|
||||
{
|
||||
case '\x00':
|
||||
case '\x01':
|
||||
case '\x02':
|
||||
case '\x03':
|
||||
case '\x04':
|
||||
case '\x05':
|
||||
case '\x06':
|
||||
case '\x07':
|
||||
case '\x08':
|
||||
case '\x0E':
|
||||
case '\x0F':
|
||||
case '\x10':
|
||||
case '\x11':
|
||||
case '\x12':
|
||||
case '\x13':
|
||||
case '\x14':
|
||||
case '\x15':
|
||||
case '\x16':
|
||||
case '\x17':
|
||||
case '\x18':
|
||||
case '\x19':
|
||||
case '\x1A':
|
||||
case '\x1B':
|
||||
case '\x7F':
|
||||
return Direction_Boundary_Neutral;
|
||||
switch (character)
|
||||
{
|
||||
case '\x00':
|
||||
case '\x01':
|
||||
case '\x02':
|
||||
case '\x03':
|
||||
case '\x04':
|
||||
case '\x05':
|
||||
case '\x06':
|
||||
case '\x07':
|
||||
case '\x08':
|
||||
case '\x0E':
|
||||
case '\x0F':
|
||||
case '\x10':
|
||||
case '\x11':
|
||||
case '\x12':
|
||||
case '\x13':
|
||||
case '\x14':
|
||||
case '\x15':
|
||||
case '\x16':
|
||||
case '\x17':
|
||||
case '\x18':
|
||||
case '\x19':
|
||||
case '\x1A':
|
||||
case '\x1B':
|
||||
case '\x7F':
|
||||
return Direction_Boundary_Neutral;
|
||||
|
||||
case '\x09':
|
||||
case '\x0B':
|
||||
case '\x1F':
|
||||
return Direction_Segment_Separator;
|
||||
case '\x09':
|
||||
case '\x0B':
|
||||
case '\x1F':
|
||||
return Direction_Segment_Separator;
|
||||
|
||||
case '\x0A':
|
||||
case '\x0D':
|
||||
case '\x1C':
|
||||
case '\x1D':
|
||||
case '\x1E':
|
||||
return Direction_Paragraph_Separator;
|
||||
case '\x0A':
|
||||
case '\x0D':
|
||||
case '\x1C':
|
||||
case '\x1D':
|
||||
case '\x1E':
|
||||
return Direction_Paragraph_Separator;
|
||||
|
||||
case '\x0C':
|
||||
case ' ':
|
||||
return Direction_White_Space;
|
||||
case '\x0C':
|
||||
case ' ':
|
||||
return Direction_White_Space;
|
||||
|
||||
case '!':
|
||||
case '"':
|
||||
case '&':
|
||||
case '\'':
|
||||
case '(':
|
||||
case ')':
|
||||
case '*':
|
||||
case ';':
|
||||
case '<':
|
||||
case '=':
|
||||
case '>':
|
||||
case '?':
|
||||
case '@':
|
||||
case '[':
|
||||
case '\\':
|
||||
case ']':
|
||||
case '^':
|
||||
case '_':
|
||||
case '`':
|
||||
case '{':
|
||||
case '|':
|
||||
case '}':
|
||||
case '~':
|
||||
return Direction_Other_Neutral;
|
||||
case '!':
|
||||
case '"':
|
||||
case '&':
|
||||
case '\'':
|
||||
case '(':
|
||||
case ')':
|
||||
case '*':
|
||||
case ';':
|
||||
case '<':
|
||||
case '=':
|
||||
case '>':
|
||||
case '?':
|
||||
case '@':
|
||||
case '[':
|
||||
case '\\':
|
||||
case ']':
|
||||
case '^':
|
||||
case '_':
|
||||
case '`':
|
||||
case '{':
|
||||
case '|':
|
||||
case '}':
|
||||
case '~':
|
||||
return Direction_Other_Neutral;
|
||||
|
||||
case '#':
|
||||
case '$':
|
||||
case '%':
|
||||
return Direction_European_Terminator;
|
||||
case '#':
|
||||
case '$':
|
||||
case '%':
|
||||
return Direction_European_Terminator;
|
||||
|
||||
case '+':
|
||||
case '-':
|
||||
return Direction_European_Separator;
|
||||
case '+':
|
||||
case '-':
|
||||
return Direction_European_Separator;
|
||||
|
||||
case ',':
|
||||
case '.':
|
||||
case '/':
|
||||
case ':':
|
||||
return Direction_Common_Separator;
|
||||
case ',':
|
||||
case '.':
|
||||
case '/':
|
||||
case ':':
|
||||
return Direction_Common_Separator;
|
||||
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
return Direction_European_Number;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
return Direction_European_Number;
|
||||
|
||||
case 'A':
|
||||
case 'B':
|
||||
case 'C':
|
||||
case 'D':
|
||||
case 'E':
|
||||
case 'F':
|
||||
case 'G':
|
||||
case 'H':
|
||||
case 'I':
|
||||
case 'J':
|
||||
case 'K':
|
||||
case 'L':
|
||||
case 'M':
|
||||
case 'N':
|
||||
case 'O':
|
||||
case 'P':
|
||||
case 'Q':
|
||||
case 'R':
|
||||
case 'S':
|
||||
case 'T':
|
||||
case 'U':
|
||||
case 'V':
|
||||
case 'W':
|
||||
case 'X':
|
||||
case 'Y':
|
||||
case 'Z':
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f':
|
||||
case 'g':
|
||||
case 'h':
|
||||
case 'i':
|
||||
case 'j':
|
||||
case 'k':
|
||||
case 'l':
|
||||
case 'm':
|
||||
case 'n':
|
||||
case 'o':
|
||||
case 'p':
|
||||
case 'q':
|
||||
case 'r':
|
||||
case 's':
|
||||
case 't':
|
||||
case 'u':
|
||||
case 'v':
|
||||
case 'w':
|
||||
case 'x':
|
||||
case 'y':
|
||||
case 'z':
|
||||
return Direction_Left_To_Right;
|
||||
case 'A':
|
||||
case 'B':
|
||||
case 'C':
|
||||
case 'D':
|
||||
case 'E':
|
||||
case 'F':
|
||||
case 'G':
|
||||
case 'H':
|
||||
case 'I':
|
||||
case 'J':
|
||||
case 'K':
|
||||
case 'L':
|
||||
case 'M':
|
||||
case 'N':
|
||||
case 'O':
|
||||
case 'P':
|
||||
case 'Q':
|
||||
case 'R':
|
||||
case 'S':
|
||||
case 'T':
|
||||
case 'U':
|
||||
case 'V':
|
||||
case 'W':
|
||||
case 'X':
|
||||
case 'Y':
|
||||
case 'Z':
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f':
|
||||
case 'g':
|
||||
case 'h':
|
||||
case 'i':
|
||||
case 'j':
|
||||
case 'k':
|
||||
case 'l':
|
||||
case 'm':
|
||||
case 'n':
|
||||
case 'o':
|
||||
case 'p':
|
||||
case 'q':
|
||||
case 'r':
|
||||
case 's':
|
||||
case 't':
|
||||
case 'u':
|
||||
case 'v':
|
||||
case 'w':
|
||||
case 'x':
|
||||
case 'y':
|
||||
case 'z':
|
||||
return Direction_Left_To_Right;
|
||||
|
||||
default:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return Direction_Boundary_Neutral;
|
||||
}
|
||||
|
||||
return Direction_Boundary_Neutral;
|
||||
char32_t Unicode::GetLowercase(char32_t character)
|
||||
{
|
||||
if (character >= 'A' && character <= 'Z')
|
||||
return character + ('a' - 'A');
|
||||
else
|
||||
return character;
|
||||
}
|
||||
|
||||
char32_t Unicode::GetTitlecase(char32_t character)
|
||||
{
|
||||
return GetUppercase(character);
|
||||
}
|
||||
|
||||
char32_t Unicode::GetUppercase(char32_t character)
|
||||
{
|
||||
if (character >= 'a' && character <= 'z')
|
||||
return character + ('A' - 'a');
|
||||
else
|
||||
return character;
|
||||
}
|
||||
}
|
||||
|
||||
char32_t NzUnicode::GetLowercase(char32_t character)
|
||||
{
|
||||
if (character >= 'A' && character <= 'Z')
|
||||
return character + ('a' - 'A');
|
||||
else
|
||||
return character;
|
||||
}
|
||||
|
||||
char32_t NzUnicode::GetTitlecase(char32_t character)
|
||||
{
|
||||
return GetUppercase(character);
|
||||
}
|
||||
|
||||
char32_t NzUnicode::GetUppercase(char32_t character)
|
||||
{
|
||||
if (character >= 'a' && character <= 'z')
|
||||
return character + ('A' - 'a');
|
||||
else
|
||||
return character;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -5,4 +5,7 @@
|
||||
#include <Nazara/Core/Updatable.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzUpdatable::~NzUpdatable() = default;
|
||||
namespace Nz
|
||||
{
|
||||
Updatable::~Updatable() = default;
|
||||
}
|
||||
|
||||
@@ -8,35 +8,38 @@
|
||||
#include <windows.h>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
namespace
|
||||
namespace Nz
|
||||
{
|
||||
LARGE_INTEGER frequency; // La fréquence ne varie pas pas au cours de l'exécution
|
||||
}
|
||||
|
||||
bool NzClockImplInitializeHighPrecision()
|
||||
{
|
||||
return QueryPerformanceFrequency(&frequency) != 0;
|
||||
}
|
||||
|
||||
nzUInt64 NzClockImplGetMicroseconds()
|
||||
{
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms644904(v=vs.85).aspx
|
||||
//HANDLE thread = GetCurrentThread();
|
||||
//DWORD oldMask = SetThreadAffinityMask(thread, 1);
|
||||
|
||||
LARGE_INTEGER time;
|
||||
QueryPerformanceCounter(&time);
|
||||
|
||||
//SetThreadAffinityMask(thread, oldMask);
|
||||
|
||||
return time.QuadPart*1000000ULL / frequency.QuadPart;
|
||||
}
|
||||
|
||||
nzUInt64 NzClockImplGetMilliseconds()
|
||||
{
|
||||
#ifdef NAZARA_PLATFORM_WINDOWS_VISTA
|
||||
return GetTickCount64();
|
||||
#else
|
||||
return GetTickCount();
|
||||
#endif
|
||||
namespace
|
||||
{
|
||||
LARGE_INTEGER s_frequency; // La fréquence ne varie pas pas au cours de l'exécution
|
||||
}
|
||||
|
||||
bool ClockImplInitializeHighPrecision()
|
||||
{
|
||||
return QueryPerformanceFrequency(&s_frequency) != 0;
|
||||
}
|
||||
|
||||
UInt64 ClockImplGetElapsedMicroseconds()
|
||||
{
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms644904(v=vs.85).aspx
|
||||
//HANDLE thread = GetCurrentThread();
|
||||
//DWORD oldMask = SetThreadAffinityMask(thread, 1);
|
||||
|
||||
LARGE_INTEGER time;
|
||||
QueryPerformanceCounter(&time);
|
||||
|
||||
//SetThreadAffinityMask(thread, oldMask);
|
||||
|
||||
return time.QuadPart*1000000ULL / s_frequency.QuadPart;
|
||||
}
|
||||
|
||||
UInt64 ClockImplGetElapsedMilliseconds()
|
||||
{
|
||||
#ifdef NAZARA_PLATFORM_WINDOWS_VISTA
|
||||
return GetTickCount64();
|
||||
#else
|
||||
return GetTickCount();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,8 +9,11 @@
|
||||
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
|
||||
bool NzClockImplInitializeHighPrecision();
|
||||
nzUInt64 NzClockImplGetMicroseconds();
|
||||
nzUInt64 NzClockImplGetMilliseconds();
|
||||
namespace Nz
|
||||
{
|
||||
bool ClockImplInitializeHighPrecision();
|
||||
UInt64 ClockImplGetElapsedMicroseconds();
|
||||
UInt64 ClockImplGetElapsedMilliseconds();
|
||||
}
|
||||
|
||||
#endif // NAZARA_CLOCKIMPL_WINDOWS_HPP
|
||||
|
||||
@@ -8,73 +8,77 @@
|
||||
#include <Nazara/Core/Win32/MutexImpl.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzConditionVariableImpl::NzConditionVariableImpl()
|
||||
namespace Nz
|
||||
{
|
||||
#if NAZARA_CORE_WINDOWS_VISTA
|
||||
InitializeConditionVariable(&m_cv);
|
||||
#else
|
||||
m_count = 0;
|
||||
m_events[BROADCAST] = CreateEvent(nullptr, true, false, nullptr); // manual-reset event
|
||||
m_events[SIGNAL] = CreateEvent(nullptr, false, false, nullptr); // auto-reset event
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !NAZARA_CORE_WINDOWS_VISTA
|
||||
NzConditionVariableImpl::~NzConditionVariableImpl()
|
||||
{
|
||||
CloseHandle(m_events[BROADCAST]);
|
||||
CloseHandle(m_events[SIGNAL]);
|
||||
}
|
||||
#endif
|
||||
|
||||
void NzConditionVariableImpl::Signal()
|
||||
{
|
||||
#if NAZARA_CORE_WINDOWS_VISTA
|
||||
WakeConditionVariable(&m_cv);
|
||||
#else
|
||||
if (m_count > 0)
|
||||
SetEvent(m_events[SIGNAL]);
|
||||
#endif
|
||||
}
|
||||
|
||||
void NzConditionVariableImpl::SignalAll()
|
||||
{
|
||||
#if NAZARA_CORE_WINDOWS_VISTA
|
||||
WakeAllConditionVariable(&m_cv);
|
||||
#else
|
||||
if (m_count > 0)
|
||||
SetEvent(m_events[BROADCAST]);
|
||||
#endif
|
||||
}
|
||||
|
||||
void NzConditionVariableImpl::Wait(NzMutexImpl* mutex)
|
||||
{
|
||||
Wait(mutex, INFINITE);
|
||||
}
|
||||
|
||||
bool NzConditionVariableImpl::Wait(NzMutexImpl* mutex, nzUInt32 timeout)
|
||||
{
|
||||
#if NAZARA_CORE_WINDOWS_VISTA
|
||||
return SleepConditionVariableCS(&m_cv, &mutex->m_criticalSection, timeout);
|
||||
#else
|
||||
m_count++;
|
||||
|
||||
// It's ok to release the mutex here since Win32
|
||||
// manual-reset events maintain state when used with SetEvent.
|
||||
// This avoids the "lost wakeup" bug...
|
||||
LeaveCriticalSection(&mutex->m_criticalSection);
|
||||
|
||||
// Wait for either event to become signaled due to Signal being called or SignalAll being called.
|
||||
int result = WaitForMultipleObjects(2, m_events, false, timeout);
|
||||
|
||||
// Some thread called SignalAll
|
||||
if (--m_count == 0 && result == WAIT_OBJECT_0 + BROADCAST)
|
||||
// We're the last waiter to be notified or to stop waiting, so reset the manual event.
|
||||
ResetEvent(m_events[BROADCAST]);
|
||||
|
||||
// Reacquire the mutex.
|
||||
EnterCriticalSection(&mutex->m_criticalSection);
|
||||
|
||||
return result != WAIT_TIMEOUT;
|
||||
ConditionVariableImpl::ConditionVariableImpl()
|
||||
{
|
||||
#if NAZARA_CORE_WINDOWS_VISTA
|
||||
InitializeConditionVariable(&m_cv);
|
||||
#else
|
||||
m_count = 0;
|
||||
m_events[BROADCAST] = CreateEvent(nullptr, true, false, nullptr); // manual-reset event
|
||||
m_events[SIGNAL] = CreateEvent(nullptr, false, false, nullptr); // auto-reset event
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !NAZARA_CORE_WINDOWS_VISTA
|
||||
ConditionVariableImpl::~ConditionVariableImpl()
|
||||
{
|
||||
CloseHandle(m_events[BROADCAST]);
|
||||
CloseHandle(m_events[SIGNAL]);
|
||||
}
|
||||
#endif
|
||||
|
||||
void ConditionVariableImpl::Signal()
|
||||
{
|
||||
#if NAZARA_CORE_WINDOWS_VISTA
|
||||
WakeConditionVariable(&m_cv);
|
||||
#else
|
||||
if (m_count > 0)
|
||||
SetEvent(m_events[SIGNAL]);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ConditionVariableImpl::SignalAll()
|
||||
{
|
||||
#if NAZARA_CORE_WINDOWS_VISTA
|
||||
WakeAllConditionVariable(&m_cv);
|
||||
#else
|
||||
if (m_count > 0)
|
||||
SetEvent(m_events[BROADCAST]);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ConditionVariableImpl::Wait(MutexImpl* mutex)
|
||||
{
|
||||
Wait(mutex, INFINITE);
|
||||
}
|
||||
|
||||
bool ConditionVariableImpl::Wait(MutexImpl* mutex, UInt32 timeout)
|
||||
{
|
||||
#if NAZARA_CORE_WINDOWS_VISTA
|
||||
return SleepConditionVariableCS(&m_cv, &mutex->m_criticalSection, timeout);
|
||||
#else
|
||||
m_count++;
|
||||
|
||||
// It's ok to release the mutex here since Win32
|
||||
// manual-reset events maintain state when used with SetEvent.
|
||||
// This avoids the "lost wakeup" bug...
|
||||
LeaveCriticalSection(&mutex->m_criticalSection);
|
||||
|
||||
// Wait for either event to become signaled due to Signal being called or SignalAll being called.
|
||||
int result = WaitForMultipleObjects(2, m_events, false, timeout);
|
||||
|
||||
// Some thread called SignalAll
|
||||
if (--m_count == 0 && result == WAIT_OBJECT_0 + BROADCAST)
|
||||
// We're the last waiter to be notified or to stop waiting, so reset the manual event.
|
||||
ResetEvent(m_events[BROADCAST]);
|
||||
|
||||
// Reacquire the mutex.
|
||||
EnterCriticalSection(&mutex->m_criticalSection);
|
||||
|
||||
return result != WAIT_TIMEOUT;
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,39 +13,41 @@
|
||||
#include <atomic>
|
||||
#include <windows.h>
|
||||
|
||||
class NzMutexImpl;
|
||||
|
||||
class NzConditionVariableImpl
|
||||
namespace Nz
|
||||
{
|
||||
public:
|
||||
NzConditionVariableImpl();
|
||||
#if NAZARA_CORE_WINDOWS_VISTA
|
||||
~NzConditionVariableImpl() = default;
|
||||
#else
|
||||
~NzConditionVariableImpl();
|
||||
#endif
|
||||
class MutexImpl;
|
||||
|
||||
void Signal();
|
||||
void SignalAll();
|
||||
class ConditionVariableImpl
|
||||
{
|
||||
public:
|
||||
ConditionVariableImpl();
|
||||
#if NAZARA_CORE_WINDOWS_VISTA
|
||||
~ConditionVariableImpl() = default;
|
||||
#else
|
||||
~ConditionVariableImpl();
|
||||
#endif
|
||||
|
||||
void Wait(NzMutexImpl* mutex);
|
||||
bool Wait(NzMutexImpl* mutex, nzUInt32 timeout);
|
||||
void Signal();
|
||||
void SignalAll();
|
||||
|
||||
private:
|
||||
#if NAZARA_CORE_WINDOWS_VISTA
|
||||
CONDITION_VARIABLE m_cv;
|
||||
#else
|
||||
enum
|
||||
{
|
||||
SIGNAL,
|
||||
BROADCAST,
|
||||
MAX_EVENTS
|
||||
};
|
||||
void Wait(MutexImpl* mutex);
|
||||
bool Wait(MutexImpl* mutex, UInt32 timeout);
|
||||
|
||||
std::atomic_uint m_count;
|
||||
HANDLE m_events[MAX_EVENTS];
|
||||
#endif
|
||||
private:
|
||||
#if NAZARA_CORE_WINDOWS_VISTA
|
||||
CONDITION_VARIABLE m_cv;
|
||||
#else
|
||||
enum
|
||||
{
|
||||
SIGNAL,
|
||||
BROADCAST,
|
||||
MAX_EVENTS
|
||||
};
|
||||
|
||||
};
|
||||
std::atomic_uint m_count;
|
||||
HANDLE m_events[MAX_EVENTS];
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NAZARA_CONDITIONVARIABLEIMPL_HPP
|
||||
|
||||
@@ -7,113 +7,116 @@
|
||||
#include <memory>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzDirectoryImpl::NzDirectoryImpl(const NzDirectory* parent)
|
||||
namespace Nz
|
||||
{
|
||||
NazaraUnused(parent);
|
||||
}
|
||||
|
||||
void NzDirectoryImpl::Close()
|
||||
{
|
||||
FindClose(m_handle);
|
||||
}
|
||||
|
||||
NzString NzDirectoryImpl::GetResultName() const
|
||||
{
|
||||
return NzString::Unicode(m_result.cFileName);
|
||||
}
|
||||
|
||||
nzUInt64 NzDirectoryImpl::GetResultSize() const
|
||||
{
|
||||
LARGE_INTEGER size;
|
||||
size.HighPart = m_result.nFileSizeHigh;
|
||||
size.LowPart = m_result.nFileSizeLow;
|
||||
|
||||
return size.QuadPart;
|
||||
}
|
||||
|
||||
bool NzDirectoryImpl::IsResultDirectory() const
|
||||
{
|
||||
if (m_result.dwFileAttributes != INVALID_FILE_ATTRIBUTES)
|
||||
return (m_result.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NzDirectoryImpl::NextResult()
|
||||
{
|
||||
if (m_firstCall) // Nous devons ignorer le premier appel car FindFirstFile nous a déjà renvoyé des résultats
|
||||
DirectoryImpl::DirectoryImpl(const Directory* parent)
|
||||
{
|
||||
m_firstCall = false;
|
||||
return true;
|
||||
NazaraUnused(parent);
|
||||
}
|
||||
|
||||
if (FindNextFileW(m_handle, &m_result))
|
||||
return true;
|
||||
else
|
||||
void DirectoryImpl::Close()
|
||||
{
|
||||
if (GetLastError() != ERROR_NO_MORE_FILES)
|
||||
NazaraError("Unable to get next result: " + NzError::GetLastSystemError());
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool NzDirectoryImpl::Open(const NzString& dirPath)
|
||||
{
|
||||
NzString searchPath = dirPath + "\\*";
|
||||
|
||||
m_handle = FindFirstFileW(searchPath.GetWideString().data(), &m_result);
|
||||
if (m_handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
NazaraError("Unable to open directory: " + NzError::GetLastSystemError());
|
||||
return false;
|
||||
FindClose(m_handle);
|
||||
}
|
||||
|
||||
m_firstCall = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzDirectoryImpl::Create(const NzString& dirPath)
|
||||
{
|
||||
return (CreateDirectoryW(dirPath.GetWideString().data(), nullptr) != 0) || GetLastError() == ERROR_ALREADY_EXISTS;
|
||||
}
|
||||
|
||||
bool NzDirectoryImpl::Exists(const NzString& dirPath)
|
||||
{
|
||||
DWORD attributes = GetFileAttributesW(dirPath.GetWideString().data());
|
||||
if (attributes != INVALID_FILE_ATTRIBUTES)
|
||||
return (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
NzString NzDirectoryImpl::GetCurrent()
|
||||
{
|
||||
NzString currentPath;
|
||||
std::unique_ptr<wchar_t[]> path(new wchar_t[MAX_PATH]);
|
||||
|
||||
unsigned int size = GetCurrentDirectoryW(MAX_PATH, path.get());
|
||||
if (size > MAX_PATH) // La taille prends en compte le caractère nul
|
||||
String DirectoryImpl::GetResultName() const
|
||||
{
|
||||
path.reset(new wchar_t[size]);
|
||||
if (GetCurrentDirectoryW(size, path.get()) != 0)
|
||||
currentPath = NzString::Unicode(path.get());
|
||||
return String::Unicode(m_result.cFileName);
|
||||
}
|
||||
|
||||
UInt64 DirectoryImpl::GetResultSize() const
|
||||
{
|
||||
LARGE_INTEGER size;
|
||||
size.HighPart = m_result.nFileSizeHigh;
|
||||
size.LowPart = m_result.nFileSizeLow;
|
||||
|
||||
return size.QuadPart;
|
||||
}
|
||||
|
||||
bool DirectoryImpl::IsResultDirectory() const
|
||||
{
|
||||
if (m_result.dwFileAttributes != INVALID_FILE_ATTRIBUTES)
|
||||
return (m_result.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
|
||||
else
|
||||
NazaraError("Unable to get current directory: " + NzError::GetLastSystemError());
|
||||
return false;
|
||||
}
|
||||
else if (size == 0)
|
||||
NazaraError("Unable to get current directory: " + NzError::GetLastSystemError());
|
||||
else
|
||||
currentPath = NzString::Unicode(path.get());
|
||||
|
||||
return currentPath;
|
||||
}
|
||||
|
||||
bool NzDirectoryImpl::Remove(const NzString& dirPath)
|
||||
{
|
||||
bool success = RemoveDirectoryW(dirPath.GetWideString().data()) != 0;
|
||||
|
||||
DWORD error = GetLastError();
|
||||
return success || error == ERROR_FILE_NOT_FOUND || error == ERROR_PATH_NOT_FOUND;
|
||||
bool DirectoryImpl::NextResult()
|
||||
{
|
||||
if (m_firstCall) // Nous devons ignorer le premier appel car FindFirstFile nous a déjà renvoyé des résultats
|
||||
{
|
||||
m_firstCall = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (FindNextFileW(m_handle, &m_result))
|
||||
return true;
|
||||
else
|
||||
{
|
||||
if (GetLastError() != ERROR_NO_MORE_FILES)
|
||||
NazaraError("Unable to get next result: " + Error::GetLastSystemError());
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool DirectoryImpl::Open(const String& dirPath)
|
||||
{
|
||||
String searchPath = dirPath + "\\*";
|
||||
|
||||
m_handle = FindFirstFileW(searchPath.GetWideString().data(), &m_result);
|
||||
if (m_handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
NazaraError("Unable to open directory: " + Error::GetLastSystemError());
|
||||
return false;
|
||||
}
|
||||
|
||||
m_firstCall = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DirectoryImpl::Create(const String& dirPath)
|
||||
{
|
||||
return (CreateDirectoryW(dirPath.GetWideString().data(), nullptr) != 0) || GetLastError() == ERROR_ALREADY_EXISTS;
|
||||
}
|
||||
|
||||
bool DirectoryImpl::Exists(const String& dirPath)
|
||||
{
|
||||
DWORD attributes = GetFileAttributesW(dirPath.GetWideString().data());
|
||||
if (attributes != INVALID_FILE_ATTRIBUTES)
|
||||
return (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
String DirectoryImpl::GetCurrent()
|
||||
{
|
||||
String currentPath;
|
||||
std::unique_ptr<wchar_t[]> path(new wchar_t[MAX_PATH]);
|
||||
|
||||
unsigned int size = GetCurrentDirectoryW(MAX_PATH, path.get());
|
||||
if (size > MAX_PATH) // La taille prends en compte le caractère nul
|
||||
{
|
||||
path.reset(new wchar_t[size]);
|
||||
if (GetCurrentDirectoryW(size, path.get()) != 0)
|
||||
currentPath = String::Unicode(path.get());
|
||||
else
|
||||
NazaraError("Unable to get current directory: " + Error::GetLastSystemError());
|
||||
}
|
||||
else if (size == 0)
|
||||
NazaraError("Unable to get current directory: " + Error::GetLastSystemError());
|
||||
else
|
||||
currentPath = String::Unicode(path.get());
|
||||
|
||||
return currentPath;
|
||||
}
|
||||
|
||||
bool DirectoryImpl::Remove(const String& dirPath)
|
||||
{
|
||||
bool success = RemoveDirectoryW(dirPath.GetWideString().data()) != 0;
|
||||
|
||||
DWORD error = GetLastError();
|
||||
return success || error == ERROR_FILE_NOT_FOUND || error == ERROR_PATH_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,40 +10,43 @@
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
#include <windows.h>
|
||||
|
||||
class NzDirectory;
|
||||
class NzString;
|
||||
|
||||
class NzDirectoryImpl
|
||||
namespace Nz
|
||||
{
|
||||
public:
|
||||
NzDirectoryImpl(const NzDirectory* parent);
|
||||
NzDirectoryImpl(const NzDirectoryImpl&) = delete;
|
||||
NzDirectoryImpl(NzDirectoryImpl&&) = delete; ///TODO
|
||||
~NzDirectoryImpl() = default;
|
||||
class Directory;
|
||||
class String;
|
||||
|
||||
void Close();
|
||||
class DirectoryImpl
|
||||
{
|
||||
public:
|
||||
DirectoryImpl(const Directory* parent);
|
||||
DirectoryImpl(const DirectoryImpl&) = delete;
|
||||
DirectoryImpl(DirectoryImpl&&) = delete; ///TODO
|
||||
~DirectoryImpl() = default;
|
||||
|
||||
NzString GetResultName() const;
|
||||
nzUInt64 GetResultSize() const;
|
||||
void Close();
|
||||
|
||||
bool IsResultDirectory() const;
|
||||
String GetResultName() const;
|
||||
UInt64 GetResultSize() const;
|
||||
|
||||
bool NextResult();
|
||||
bool IsResultDirectory() const;
|
||||
|
||||
bool Open(const NzString& dirPath);
|
||||
bool NextResult();
|
||||
|
||||
NzDirectoryImpl& operator=(const NzDirectoryImpl&) = delete;
|
||||
NzDirectoryImpl& operator=(NzDirectoryImpl&&) = delete; ///TODO
|
||||
bool Open(const String& dirPath);
|
||||
|
||||
static bool Create(const NzString& dirPath);
|
||||
static bool Exists(const NzString& dirPath);
|
||||
static NzString GetCurrent();
|
||||
static bool Remove(const NzString& dirPath);
|
||||
DirectoryImpl& operator=(const DirectoryImpl&) = delete;
|
||||
DirectoryImpl& operator=(DirectoryImpl&&) = delete; ///TODO
|
||||
|
||||
private:
|
||||
HANDLE m_handle;
|
||||
WIN32_FIND_DATAW m_result;
|
||||
bool m_firstCall;
|
||||
};
|
||||
static bool Create(const String& dirPath);
|
||||
static bool Exists(const String& dirPath);
|
||||
static String GetCurrent();
|
||||
static bool Remove(const String& dirPath);
|
||||
|
||||
private:
|
||||
HANDLE m_handle;
|
||||
WIN32_FIND_DATAW m_result;
|
||||
bool m_firstCall;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NAZARA_DIRECTORYIMPL_HPP
|
||||
|
||||
@@ -10,37 +10,41 @@
|
||||
#include <memory>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzDynLibImpl::NzDynLibImpl(NzDynLib* parent)
|
||||
namespace Nz
|
||||
{
|
||||
NazaraUnused(parent);
|
||||
}
|
||||
|
||||
NzDynLibFunc NzDynLibImpl::GetSymbol(const NzString& symbol, NzString* errorMessage) const
|
||||
{
|
||||
NzDynLibFunc sym = reinterpret_cast<NzDynLibFunc>(GetProcAddress(m_handle, symbol.GetConstBuffer()));
|
||||
if (!sym)
|
||||
*errorMessage = NzError::GetLastSystemError();
|
||||
|
||||
return sym;
|
||||
}
|
||||
|
||||
bool NzDynLibImpl::Load(const NzString& libraryPath, NzString* errorMessage)
|
||||
{
|
||||
NzString path = libraryPath;
|
||||
if (!path.EndsWith(".dll"))
|
||||
path += ".dll";
|
||||
|
||||
m_handle = LoadLibraryExW(path.GetWideString().data(), nullptr, (NzFile::IsAbsolute(path)) ? LOAD_WITH_ALTERED_SEARCH_PATH : 0);
|
||||
if (m_handle)
|
||||
return true;
|
||||
else
|
||||
DynLibImpl::DynLibImpl(DynLib* parent)
|
||||
{
|
||||
*errorMessage = NzError::GetLastSystemError();
|
||||
return false;
|
||||
NazaraUnused(parent);
|
||||
}
|
||||
|
||||
DynLibFunc DynLibImpl::GetSymbol(const String& symbol, String* errorMessage) const
|
||||
{
|
||||
DynLibFunc sym = reinterpret_cast<DynLibFunc>(GetProcAddress(m_handle, symbol.GetConstBuffer()));
|
||||
if (!sym)
|
||||
*errorMessage = Error::GetLastSystemError();
|
||||
|
||||
return sym;
|
||||
}
|
||||
|
||||
bool DynLibImpl::Load(const String& libraryPath, String* errorMessage)
|
||||
{
|
||||
String path = libraryPath;
|
||||
if (!path.EndsWith(".dll"))
|
||||
path += ".dll";
|
||||
|
||||
m_handle = LoadLibraryExW(path.GetWideString().data(), nullptr, (File::IsAbsolute(path)) ? LOAD_WITH_ALTERED_SEARCH_PATH : 0);
|
||||
if (m_handle)
|
||||
return true;
|
||||
else
|
||||
{
|
||||
*errorMessage = Error::GetLastSystemError();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void DynLibImpl::Unload()
|
||||
{
|
||||
FreeLibrary(m_handle);
|
||||
}
|
||||
}
|
||||
|
||||
void NzDynLibImpl::Unload()
|
||||
{
|
||||
FreeLibrary(m_handle);
|
||||
}
|
||||
|
||||
@@ -11,25 +11,28 @@
|
||||
#include <Nazara/Core/DynLib.hpp>
|
||||
#include <windows.h>
|
||||
|
||||
class NzString;
|
||||
|
||||
class NzDynLibImpl
|
||||
namespace Nz
|
||||
{
|
||||
public:
|
||||
NzDynLibImpl(NzDynLib* m_parent);
|
||||
NzDynLibImpl(const NzDynLibImpl&) = delete;
|
||||
NzDynLibImpl(NzDynLibImpl&&) = delete; ///TODO?
|
||||
~NzDynLibImpl() = default;
|
||||
class String;
|
||||
|
||||
NzDynLibFunc GetSymbol(const NzString& symbol, NzString* errorMessage) const;
|
||||
bool Load(const NzString& libraryPath, NzString* errorMessage);
|
||||
void Unload();
|
||||
class DynLibImpl
|
||||
{
|
||||
public:
|
||||
DynLibImpl(DynLib* m_parent);
|
||||
DynLibImpl(const DynLibImpl&) = delete;
|
||||
DynLibImpl(DynLibImpl&&) = delete; ///TODO?
|
||||
~DynLibImpl() = default;
|
||||
|
||||
NzDynLibImpl& operator=(const NzDynLibImpl&) = delete;
|
||||
NzDynLibImpl& operator=(NzDynLibImpl&&) = delete; ///TODO?
|
||||
DynLibFunc GetSymbol(const String& symbol, String* errorMessage) const;
|
||||
bool Load(const String& libraryPath, String* errorMessage);
|
||||
void Unload();
|
||||
|
||||
private:
|
||||
HMODULE m_handle;
|
||||
};
|
||||
DynLibImpl& operator=(const DynLibImpl&) = delete;
|
||||
DynLibImpl& operator=(DynLibImpl&&) = delete; ///TODO?
|
||||
|
||||
private:
|
||||
HMODULE m_handle;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NAZARA_DYNLIBIMPL_HPP
|
||||
|
||||
@@ -8,288 +8,291 @@
|
||||
#include <memory>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzFileImpl::NzFileImpl(const NzFile* parent) :
|
||||
m_endOfFile(false),
|
||||
m_endOfFileUpdated(true)
|
||||
namespace Nz
|
||||
{
|
||||
NazaraUnused(parent);
|
||||
}
|
||||
|
||||
void NzFileImpl::Close()
|
||||
{
|
||||
CloseHandle(m_handle);
|
||||
}
|
||||
|
||||
bool NzFileImpl::EndOfFile() const
|
||||
{
|
||||
if (!m_endOfFileUpdated)
|
||||
FileImpl::FileImpl(const File* parent) :
|
||||
m_endOfFile(false),
|
||||
m_endOfFileUpdated(true)
|
||||
{
|
||||
LARGE_INTEGER fileSize;
|
||||
if (!GetFileSizeEx(m_handle, &fileSize))
|
||||
fileSize.QuadPart = 0;
|
||||
|
||||
m_endOfFile = (GetCursorPos() >= static_cast<nzUInt64>(fileSize.QuadPart));
|
||||
m_endOfFileUpdated = true;
|
||||
NazaraUnused(parent);
|
||||
}
|
||||
|
||||
return m_endOfFile;
|
||||
}
|
||||
|
||||
void NzFileImpl::Flush()
|
||||
{
|
||||
if (!FlushFileBuffers(m_handle))
|
||||
NazaraError("Unable to flush file: " + NzError::GetLastSystemError());
|
||||
}
|
||||
|
||||
nzUInt64 NzFileImpl::GetCursorPos() const
|
||||
{
|
||||
LARGE_INTEGER zero;
|
||||
zero.QuadPart = 0;
|
||||
|
||||
LARGE_INTEGER position;
|
||||
SetFilePointerEx(m_handle, zero, &position, FILE_CURRENT);
|
||||
|
||||
return position.QuadPart;
|
||||
}
|
||||
|
||||
bool NzFileImpl::Open(const NzString& filePath, unsigned int mode)
|
||||
{
|
||||
DWORD access;
|
||||
DWORD shareMode = FILE_SHARE_READ;
|
||||
DWORD openMode;
|
||||
if (mode & nzOpenMode_ReadOnly)
|
||||
void FileImpl::Close()
|
||||
{
|
||||
access = GENERIC_READ;
|
||||
openMode = OPEN_EXISTING;
|
||||
CloseHandle(m_handle);
|
||||
}
|
||||
else if (mode & nzOpenMode_ReadWrite)
|
||||
|
||||
bool FileImpl::EndOfFile() const
|
||||
{
|
||||
if (mode & nzOpenMode_Append)
|
||||
access = FILE_APPEND_DATA;
|
||||
else
|
||||
access = GENERIC_READ | GENERIC_WRITE;
|
||||
|
||||
if (mode & nzOpenMode_Truncate)
|
||||
openMode = CREATE_ALWAYS;
|
||||
else
|
||||
openMode = OPEN_ALWAYS;
|
||||
}
|
||||
else if (mode & nzOpenMode_WriteOnly)
|
||||
{
|
||||
if (mode & nzOpenMode_Append)
|
||||
access = FILE_APPEND_DATA;
|
||||
else
|
||||
access = GENERIC_WRITE;
|
||||
|
||||
if (mode & nzOpenMode_Truncate)
|
||||
openMode = CREATE_ALWAYS;
|
||||
else
|
||||
openMode = OPEN_ALWAYS;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
if ((mode & nzOpenMode_Lock) == 0)
|
||||
shareMode |= FILE_SHARE_WRITE;
|
||||
|
||||
m_handle = CreateFileW(filePath.GetWideString().data(), access, shareMode, nullptr, openMode, 0, nullptr);
|
||||
return m_handle != INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
std::size_t NzFileImpl::Read(void* buffer, std::size_t size)
|
||||
{
|
||||
//nzUInt64 oldCursorPos = GetCursorPos();
|
||||
|
||||
DWORD read = 0;
|
||||
if (ReadFile(m_handle, buffer, size, &read, nullptr))
|
||||
{
|
||||
m_endOfFile = (read != size);
|
||||
m_endOfFileUpdated = true;
|
||||
|
||||
return read;
|
||||
///FIXME: D'après la documentation, read vaut 0 si ReadFile atteint la fin du fichier
|
||||
/// D'après les tests, ce n'est pas le cas, la taille lue est inférieure à la taille en argument, mais pas nulle
|
||||
/// Peut-être ais-je mal compris la documentation
|
||||
/// Le correctif (dans le cas où la doc serait vraie) est commenté en début de fonction et après ce commentaire
|
||||
/// Il est cependant plus lourd, et ne fonctionne pas avec le comportement observé de la fonction
|
||||
/*
|
||||
if (read == 0)
|
||||
if (!m_endOfFileUpdated)
|
||||
{
|
||||
// Si nous atteignons la fin du fichier, la taille lue vaut 0
|
||||
// pour renvoyer le nombre d'octets lus nous comparons la position du curseur
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa365690(v=vs.85).aspx
|
||||
m_endOfFile = true;
|
||||
LARGE_INTEGER fileSize;
|
||||
if (!GetFileSizeEx(m_handle, &fileSize))
|
||||
fileSize.QuadPart = 0;
|
||||
|
||||
m_endOfFile = (GetCursorPos() >= static_cast<UInt64>(fileSize.QuadPart));
|
||||
m_endOfFileUpdated = true;
|
||||
}
|
||||
|
||||
return m_endOfFile;
|
||||
}
|
||||
|
||||
void FileImpl::Flush()
|
||||
{
|
||||
if (!FlushFileBuffers(m_handle))
|
||||
NazaraError("Unable to flush file: " + Error::GetLastSystemError());
|
||||
}
|
||||
|
||||
UInt64 FileImpl::GetCursorPos() const
|
||||
{
|
||||
LARGE_INTEGER zero;
|
||||
zero.QuadPart = 0;
|
||||
|
||||
LARGE_INTEGER position;
|
||||
SetFilePointerEx(m_handle, zero, &position, FILE_CURRENT);
|
||||
|
||||
return position.QuadPart;
|
||||
}
|
||||
|
||||
bool FileImpl::Open(const String& filePath, unsigned int mode)
|
||||
{
|
||||
DWORD access;
|
||||
DWORD shareMode = FILE_SHARE_READ;
|
||||
DWORD openMode;
|
||||
if (mode & OpenMode_ReadOnly)
|
||||
{
|
||||
access = GENERIC_READ;
|
||||
openMode = OPEN_EXISTING;
|
||||
}
|
||||
else if (mode & OpenMode_ReadWrite)
|
||||
{
|
||||
if (mode & OpenMode_Append)
|
||||
access = FILE_APPEND_DATA;
|
||||
else
|
||||
access = GENERIC_READ | GENERIC_WRITE;
|
||||
|
||||
if (mode & OpenMode_Truncate)
|
||||
openMode = CREATE_ALWAYS;
|
||||
else
|
||||
openMode = OPEN_ALWAYS;
|
||||
}
|
||||
else if (mode & OpenMode_WriteOnly)
|
||||
{
|
||||
if (mode & OpenMode_Append)
|
||||
access = FILE_APPEND_DATA;
|
||||
else
|
||||
access = GENERIC_WRITE;
|
||||
|
||||
if (mode & OpenMode_Truncate)
|
||||
openMode = CREATE_ALWAYS;
|
||||
else
|
||||
openMode = OPEN_ALWAYS;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
if ((mode & OpenMode_Lock) == 0)
|
||||
shareMode |= FILE_SHARE_WRITE;
|
||||
|
||||
m_handle = CreateFileW(filePath.GetWideString().data(), access, shareMode, nullptr, openMode, 0, nullptr);
|
||||
return m_handle != INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
std::size_t FileImpl::Read(void* buffer, std::size_t size)
|
||||
{
|
||||
//UInt64 oldCursorPos = GetCursorPos();
|
||||
|
||||
DWORD read = 0;
|
||||
if (ReadFile(m_handle, buffer, size, &read, nullptr))
|
||||
{
|
||||
m_endOfFile = (read != size);
|
||||
m_endOfFileUpdated = true;
|
||||
|
||||
return GetCursorPos()-oldCursorPos;
|
||||
return read;
|
||||
///FIXME: D'après la documentation, read vaut 0 si ReadFile atteint la fin du fichier
|
||||
/// D'après les tests, ce n'est pas le cas, la taille lue est inférieure à la taille en argument, mais pas nulle
|
||||
/// Peut-être ais-je mal compris la documentation
|
||||
/// Le correctif (dans le cas où la doc serait vraie) est commenté en début de fonction et après ce commentaire
|
||||
/// Il est cependant plus lourd, et ne fonctionne pas avec le comportement observé de la fonction
|
||||
/*
|
||||
if (read == 0)
|
||||
{
|
||||
// Si nous atteignons la fin du fichier, la taille lue vaut 0
|
||||
// pour renvoyer le nombre d'octets lus nous comparons la position du curseur
|
||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa365690(v=vs.85).aspx
|
||||
m_endOfFile = true;
|
||||
m_endOfFileUpdated = true;
|
||||
|
||||
return GetCursorPos()-oldCursorPos;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_endOfFileUpdated = false;
|
||||
return read;
|
||||
}
|
||||
*/
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool FileImpl::SetCursorPos(CursorPosition pos, Int64 offset)
|
||||
{
|
||||
DWORD moveMethod;
|
||||
switch (pos)
|
||||
{
|
||||
m_endOfFileUpdated = false;
|
||||
return read;
|
||||
case CursorPosition_AtBegin:
|
||||
moveMethod = FILE_BEGIN;
|
||||
break;
|
||||
|
||||
case CursorPosition_AtCurrent:
|
||||
moveMethod = FILE_CURRENT;
|
||||
break;
|
||||
|
||||
case CursorPosition_AtEnd:
|
||||
moveMethod = FILE_END;
|
||||
break;
|
||||
|
||||
default:
|
||||
NazaraInternalError("Cursor position not handled (0x" + String::Number(pos, 16) + ')');
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
LARGE_INTEGER distance;
|
||||
distance.QuadPart = offset;
|
||||
|
||||
m_endOfFileUpdated = false;
|
||||
|
||||
return SetFilePointerEx(m_handle, distance, nullptr, moveMethod) != 0;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool NzFileImpl::SetCursorPos(nzCursorPosition pos, nzInt64 offset)
|
||||
{
|
||||
DWORD moveMethod;
|
||||
switch (pos)
|
||||
std::size_t FileImpl::Write(const void* buffer, std::size_t size)
|
||||
{
|
||||
case nzCursorPosition_AtBegin:
|
||||
moveMethod = FILE_BEGIN;
|
||||
break;
|
||||
DWORD written = 0;
|
||||
|
||||
case nzCursorPosition_AtCurrent:
|
||||
moveMethod = FILE_CURRENT;
|
||||
break;
|
||||
LARGE_INTEGER cursorPos;
|
||||
cursorPos.QuadPart = GetCursorPos();
|
||||
|
||||
case nzCursorPosition_AtEnd:
|
||||
moveMethod = FILE_END;
|
||||
break;
|
||||
LockFile(m_handle, cursorPos.LowPart, cursorPos.HighPart, size, 0);
|
||||
WriteFile(m_handle, buffer, size, &written, nullptr);
|
||||
UnlockFile(m_handle, cursorPos.LowPart, cursorPos.HighPart, size, 0);
|
||||
|
||||
default:
|
||||
NazaraInternalError("Cursor position not handled (0x" + NzString::Number(pos, 16) + ')');
|
||||
m_endOfFileUpdated = false;
|
||||
|
||||
return written;
|
||||
}
|
||||
|
||||
bool FileImpl::Copy(const String& sourcePath, const String& targetPath)
|
||||
{
|
||||
if (CopyFileW(sourcePath.GetWideString().data(), targetPath.GetWideString().data(), false))
|
||||
return true;
|
||||
else
|
||||
{
|
||||
NazaraError("Failed to copy file: " + Error::GetLastSystemError());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
LARGE_INTEGER distance;
|
||||
distance.QuadPart = offset;
|
||||
|
||||
m_endOfFileUpdated = false;
|
||||
|
||||
return SetFilePointerEx(m_handle, distance, nullptr, moveMethod) != 0;
|
||||
}
|
||||
|
||||
std::size_t NzFileImpl::Write(const void* buffer, std::size_t size)
|
||||
{
|
||||
DWORD written = 0;
|
||||
|
||||
LARGE_INTEGER cursorPos;
|
||||
cursorPos.QuadPart = GetCursorPos();
|
||||
|
||||
LockFile(m_handle, cursorPos.LowPart, cursorPos.HighPart, size, 0);
|
||||
WriteFile(m_handle, buffer, size, &written, nullptr);
|
||||
UnlockFile(m_handle, cursorPos.LowPart, cursorPos.HighPart, size, 0);
|
||||
|
||||
m_endOfFileUpdated = false;
|
||||
|
||||
return written;
|
||||
}
|
||||
|
||||
bool NzFileImpl::Copy(const NzString& sourcePath, const NzString& targetPath)
|
||||
{
|
||||
if (CopyFileW(sourcePath.GetWideString().data(), targetPath.GetWideString().data(), false))
|
||||
return true;
|
||||
else
|
||||
bool FileImpl::Delete(const String& filePath)
|
||||
{
|
||||
NazaraError("Failed to copy file: " + NzError::GetLastSystemError());
|
||||
return false;
|
||||
if (DeleteFileW(filePath.GetWideString().data()))
|
||||
return true;
|
||||
else
|
||||
{
|
||||
NazaraError("Failed to delete file (" + filePath + "): " + Error::GetLastSystemError());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool NzFileImpl::Delete(const NzString& filePath)
|
||||
{
|
||||
if (DeleteFileW(filePath.GetWideString().data()))
|
||||
return true;
|
||||
else
|
||||
bool FileImpl::Exists(const String& filePath)
|
||||
{
|
||||
NazaraError("Failed to delete file (" + filePath + "): " + NzError::GetLastSystemError());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
HANDLE handle = CreateFileW(filePath.GetWideString().data(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
|
||||
bool NzFileImpl::Exists(const NzString& filePath)
|
||||
{
|
||||
HANDLE handle = CreateFileW(filePath.GetWideString().data(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
|
||||
CloseHandle(handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
time_t NzFileImpl::GetCreationTime(const NzString& filePath)
|
||||
{
|
||||
HANDLE handle = CreateFileW(filePath.GetWideString().data(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
return 0;
|
||||
|
||||
FILETIME creationTime;
|
||||
if (!GetFileTime(handle, &creationTime, nullptr, nullptr))
|
||||
{
|
||||
CloseHandle(handle);
|
||||
|
||||
NazaraError("Unable to get creation time: " + NzError::GetLastSystemError());
|
||||
return 0;
|
||||
}
|
||||
|
||||
CloseHandle(handle);
|
||||
return NzFileTimeToTime(&creationTime);
|
||||
}
|
||||
|
||||
time_t NzFileImpl::GetLastAccessTime(const NzString& filePath)
|
||||
{
|
||||
HANDLE handle = CreateFileW(filePath.GetWideString().data(), 0, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
return 0;
|
||||
|
||||
FILETIME accessTime;
|
||||
if (!GetFileTime(handle, nullptr, &accessTime, nullptr))
|
||||
{
|
||||
CloseHandle(handle);
|
||||
|
||||
NazaraError("Unable to get last access time: " + NzError::GetLastSystemError());
|
||||
return 0;
|
||||
}
|
||||
|
||||
CloseHandle(handle);
|
||||
return NzFileTimeToTime(&accessTime);
|
||||
}
|
||||
|
||||
time_t NzFileImpl::GetLastWriteTime(const NzString& filePath)
|
||||
{
|
||||
HANDLE handle = CreateFileW(filePath.GetWideString().data(), 0, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
return 0;
|
||||
|
||||
FILETIME writeTime;
|
||||
if (!GetFileTime(handle, nullptr, nullptr, &writeTime))
|
||||
{
|
||||
CloseHandle(handle);
|
||||
|
||||
NazaraError("Unable to get last write time: " + NzError::GetLastSystemError());
|
||||
return 0;
|
||||
}
|
||||
|
||||
CloseHandle(handle);
|
||||
return NzFileTimeToTime(&writeTime);
|
||||
}
|
||||
|
||||
nzUInt64 NzFileImpl::GetSize(const NzString& filePath)
|
||||
{
|
||||
HANDLE handle = CreateFileW(filePath.GetWideString().data(), 0, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
return 0;
|
||||
|
||||
LARGE_INTEGER fileSize;
|
||||
if (!GetFileSizeEx(handle, &fileSize))
|
||||
fileSize.QuadPart = 0;
|
||||
|
||||
CloseHandle(handle);
|
||||
return fileSize.QuadPart;
|
||||
}
|
||||
|
||||
bool NzFileImpl::Rename(const NzString& sourcePath, const NzString& targetPath)
|
||||
{
|
||||
if (MoveFileExW(sourcePath.GetWideString().data(), targetPath.GetWideString().data(), MOVEFILE_COPY_ALLOWED))
|
||||
return true;
|
||||
else
|
||||
}
|
||||
|
||||
time_t FileImpl::GetCreationTime(const String& filePath)
|
||||
{
|
||||
NazaraError("Unable to rename file: " + NzError::GetLastSystemError());
|
||||
return false;
|
||||
HANDLE handle = CreateFileW(filePath.GetWideString().data(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
return 0;
|
||||
|
||||
FILETIME creationTime;
|
||||
if (!GetFileTime(handle, &creationTime, nullptr, nullptr))
|
||||
{
|
||||
CloseHandle(handle);
|
||||
|
||||
NazaraError("Unable to get creation time: " + Error::GetLastSystemError());
|
||||
return 0;
|
||||
}
|
||||
|
||||
CloseHandle(handle);
|
||||
return FileTimeToTime(&creationTime);
|
||||
}
|
||||
|
||||
time_t FileImpl::GetLastAccessTime(const String& filePath)
|
||||
{
|
||||
HANDLE handle = CreateFileW(filePath.GetWideString().data(), 0, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
return 0;
|
||||
|
||||
FILETIME accessTime;
|
||||
if (!GetFileTime(handle, nullptr, &accessTime, nullptr))
|
||||
{
|
||||
CloseHandle(handle);
|
||||
|
||||
NazaraError("Unable to get last access time: " + Error::GetLastSystemError());
|
||||
return 0;
|
||||
}
|
||||
|
||||
CloseHandle(handle);
|
||||
return FileTimeToTime(&accessTime);
|
||||
}
|
||||
|
||||
time_t FileImpl::GetLastWriteTime(const String& filePath)
|
||||
{
|
||||
HANDLE handle = CreateFileW(filePath.GetWideString().data(), 0, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
return 0;
|
||||
|
||||
FILETIME writeTime;
|
||||
if (!GetFileTime(handle, nullptr, nullptr, &writeTime))
|
||||
{
|
||||
CloseHandle(handle);
|
||||
|
||||
NazaraError("Unable to get last write time: " + Error::GetLastSystemError());
|
||||
return 0;
|
||||
}
|
||||
|
||||
CloseHandle(handle);
|
||||
return FileTimeToTime(&writeTime);
|
||||
}
|
||||
|
||||
UInt64 FileImpl::GetSize(const String& filePath)
|
||||
{
|
||||
HANDLE handle = CreateFileW(filePath.GetWideString().data(), 0, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
return 0;
|
||||
|
||||
LARGE_INTEGER fileSize;
|
||||
if (!GetFileSizeEx(handle, &fileSize))
|
||||
fileSize.QuadPart = 0;
|
||||
|
||||
CloseHandle(handle);
|
||||
return fileSize.QuadPart;
|
||||
}
|
||||
|
||||
bool FileImpl::Rename(const String& sourcePath, const String& targetPath)
|
||||
{
|
||||
if (MoveFileExW(sourcePath.GetWideString().data(), targetPath.GetWideString().data(), MOVEFILE_COPY_ALLOWED))
|
||||
return true;
|
||||
else
|
||||
{
|
||||
NazaraError("Unable to rename file: " + Error::GetLastSystemError());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,42 +12,45 @@
|
||||
#include <ctime>
|
||||
#include <windows.h>
|
||||
|
||||
class NzFile;
|
||||
class NzString;
|
||||
|
||||
class NzFileImpl
|
||||
namespace Nz
|
||||
{
|
||||
public:
|
||||
NzFileImpl(const NzFile* parent);
|
||||
NzFileImpl(const NzFileImpl&) = delete;
|
||||
NzFileImpl(NzFileImpl&&) = delete; ///TODO
|
||||
~NzFileImpl() = default;
|
||||
class File;
|
||||
class String;
|
||||
|
||||
void Close();
|
||||
bool EndOfFile() const;
|
||||
void Flush();
|
||||
nzUInt64 GetCursorPos() const;
|
||||
bool Open(const NzString& filePath, unsigned int mode);
|
||||
std::size_t Read(void* buffer, std::size_t size);
|
||||
bool SetCursorPos(nzCursorPosition pos, nzInt64 offset);
|
||||
std::size_t Write(const void* buffer, std::size_t size);
|
||||
class FileImpl
|
||||
{
|
||||
public:
|
||||
FileImpl(const File* parent);
|
||||
FileImpl(const FileImpl&) = delete;
|
||||
FileImpl(FileImpl&&) = delete; ///TODO
|
||||
~FileImpl() = default;
|
||||
|
||||
NzFileImpl& operator=(const NzFileImpl&) = delete;
|
||||
NzFileImpl& operator=(NzFileImpl&&) = delete; ///TODO
|
||||
void Close();
|
||||
bool EndOfFile() const;
|
||||
void Flush();
|
||||
UInt64 GetCursorPos() const;
|
||||
bool Open(const String& filePath, unsigned int mode);
|
||||
std::size_t Read(void* buffer, std::size_t size);
|
||||
bool SetCursorPos(CursorPosition pos, Int64 offset);
|
||||
std::size_t Write(const void* buffer, std::size_t size);
|
||||
|
||||
static bool Copy(const NzString& sourcePath, const NzString& targetPath);
|
||||
static bool Delete(const NzString& filePath);
|
||||
static bool Exists(const NzString& filePath);
|
||||
static time_t GetCreationTime(const NzString& filePath);
|
||||
static time_t GetLastAccessTime(const NzString& filePath);
|
||||
static time_t GetLastWriteTime(const NzString& filePath);
|
||||
static nzUInt64 GetSize(const NzString& filePath);
|
||||
static bool Rename(const NzString& sourcePath, const NzString& targetPath);
|
||||
FileImpl& operator=(const FileImpl&) = delete;
|
||||
FileImpl& operator=(FileImpl&&) = delete; ///TODO
|
||||
|
||||
private:
|
||||
HANDLE m_handle;
|
||||
mutable bool m_endOfFile;
|
||||
mutable bool m_endOfFileUpdated;
|
||||
};
|
||||
static bool Copy(const String& sourcePath, const String& targetPath);
|
||||
static bool Delete(const String& filePath);
|
||||
static bool Exists(const String& filePath);
|
||||
static time_t GetCreationTime(const String& filePath);
|
||||
static time_t GetLastAccessTime(const String& filePath);
|
||||
static time_t GetLastWriteTime(const String& filePath);
|
||||
static UInt64 GetSize(const String& filePath);
|
||||
static bool Rename(const String& sourcePath, const String& targetPath);
|
||||
|
||||
private:
|
||||
HANDLE m_handle;
|
||||
mutable bool m_endOfFile;
|
||||
mutable bool m_endOfFileUpdated;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NAZARA_FILEIMPL_HPP
|
||||
|
||||
@@ -12,86 +12,89 @@
|
||||
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
void NzHardwareInfoImpl::Cpuid(nzUInt32 functionId, nzUInt32 subFunctionId, nzUInt32 registers[4])
|
||||
namespace Nz
|
||||
{
|
||||
#if defined(NAZARA_COMPILER_MSVC)
|
||||
static_assert(sizeof(nzUInt32) == sizeof(int), "Assertion failed");
|
||||
|
||||
// Visual propose une fonction intrinsèque pour le cpuid
|
||||
__cpuidex(reinterpret_cast<int*>(registers), static_cast<int>(functionId), static_cast<int>(subFunctionId));
|
||||
#elif defined(NAZARA_COMPILER_CLANG) || defined(NAZARA_COMPILER_GCC) || defined(NAZARA_COMPILER_INTEL)
|
||||
// Source: http://stackoverflow.com/questions/1666093/cpuid-implementations-in-c
|
||||
asm volatile ("cpuid" // Besoin d'être volatile ?
|
||||
: "=a" (registers[0]), "=b" (registers[1]), "=c" (registers[2]), "=d" (registers[3]) // output
|
||||
: "a" (functionId), "c" (subFunctionId)); // input
|
||||
#else
|
||||
NazaraInternalError("Cpuid has been called although it is not supported");
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned int NzHardwareInfoImpl::GetProcessorCount()
|
||||
{
|
||||
// Plus simple (et plus portable) que de passer par le CPUID
|
||||
SYSTEM_INFO infos;
|
||||
GetNativeSystemInfo(&infos);
|
||||
|
||||
return infos.dwNumberOfProcessors;
|
||||
}
|
||||
|
||||
nzUInt64 NzHardwareInfoImpl::GetTotalMemory()
|
||||
{
|
||||
MEMORYSTATUSEX memStatus;
|
||||
memStatus.dwLength = sizeof(memStatus);
|
||||
GlobalMemoryStatusEx(&memStatus);
|
||||
|
||||
return memStatus.ullTotalPhys;
|
||||
}
|
||||
|
||||
bool NzHardwareInfoImpl::IsCpuidSupported()
|
||||
{
|
||||
#ifdef NAZARA_PLATFORM_x64
|
||||
return true; // Toujours supporté sur un processeur 64 bits
|
||||
#else
|
||||
#if defined(NAZARA_COMPILER_MSVC)
|
||||
int supported;
|
||||
__asm
|
||||
void HardwareInfoImpl::Cpuid(UInt32 functionId, UInt32 subFunctionId, UInt32 registers[4])
|
||||
{
|
||||
pushfd
|
||||
pop eax
|
||||
mov ecx, eax
|
||||
xor eax, 0x200000
|
||||
push eax
|
||||
popfd
|
||||
pushfd
|
||||
pop eax
|
||||
xor eax, ecx
|
||||
mov supported, eax
|
||||
push ecx
|
||||
popfd
|
||||
};
|
||||
#if defined(NAZARA_COMPILER_MSVC)
|
||||
static_assert(sizeof(UInt32) == sizeof(int), "Assertion failed");
|
||||
|
||||
return supported != 0;
|
||||
// Visual propose une fonction intrinsèque pour le cpuid
|
||||
__cpuidex(reinterpret_cast<int*>(registers), static_cast<int>(functionId), static_cast<int>(subFunctionId));
|
||||
#elif defined(NAZARA_COMPILER_CLANG) || defined(NAZARA_COMPILER_GCC) || defined(NAZARA_COMPILER_INTEL)
|
||||
int supported;
|
||||
asm volatile (" pushfl\n"
|
||||
" pop %%eax\n"
|
||||
" mov %%eax, %%ecx\n"
|
||||
" xor $0x200000, %%eax\n"
|
||||
" push %%eax\n"
|
||||
" popfl\n"
|
||||
" pushfl\n"
|
||||
" pop %%eax\n"
|
||||
" xor %%ecx, %%eax\n"
|
||||
" mov %%eax, %0\n"
|
||||
" push %%ecx\n"
|
||||
" popfl"
|
||||
: "=m" (supported) // output
|
||||
: // input
|
||||
: "eax", "ecx", "memory"); // clobbered register
|
||||
|
||||
return supported != 0;
|
||||
// Source: http://stackoverflow.com/questions/1666093/cpuid-implementations-in-c
|
||||
asm volatile ("cpuid" // Besoin d'être volatile ?
|
||||
: "=a" (registers[0]), "=b" (registers[1]), "=c" (registers[2]), "=d" (registers[3]) // output
|
||||
: "a" (functionId), "c" (subFunctionId)); // input
|
||||
#else
|
||||
return false;
|
||||
NazaraInternalError("Cpuid has been called although it is not supported");
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned int HardwareInfoImpl::GetProcessorCount()
|
||||
{
|
||||
// Plus simple (et plus portable) que de passer par le CPUID
|
||||
SYSTEM_INFO infos;
|
||||
GetNativeSystemInfo(&infos);
|
||||
|
||||
return infos.dwNumberOfProcessors;
|
||||
}
|
||||
|
||||
UInt64 HardwareInfoImpl::GetTotalMemory()
|
||||
{
|
||||
MEMORYSTATUSEX memStatus;
|
||||
memStatus.dwLength = sizeof(memStatus);
|
||||
GlobalMemoryStatusEx(&memStatus);
|
||||
|
||||
return memStatus.ullTotalPhys;
|
||||
}
|
||||
|
||||
bool HardwareInfoImpl::IsCpuidSupported()
|
||||
{
|
||||
#ifdef NAZARA_PLATFORM_x64
|
||||
return true; // Toujours supporté sur un processeur 64 bits
|
||||
#else
|
||||
#if defined(NAZARA_COMPILER_MSVC)
|
||||
int supported;
|
||||
__asm
|
||||
{
|
||||
pushfd
|
||||
pop eax
|
||||
mov ecx, eax
|
||||
xor eax, 0x200000
|
||||
push eax
|
||||
popfd
|
||||
pushfd
|
||||
pop eax
|
||||
xor eax, ecx
|
||||
mov supported, eax
|
||||
push ecx
|
||||
popfd
|
||||
};
|
||||
|
||||
return supported != 0;
|
||||
#elif defined(NAZARA_COMPILER_CLANG) || defined(NAZARA_COMPILER_GCC) || defined(NAZARA_COMPILER_INTEL)
|
||||
int supported;
|
||||
asm volatile (" pushfl\n"
|
||||
" pop %%eax\n"
|
||||
" mov %%eax, %%ecx\n"
|
||||
" xor $0x200000, %%eax\n"
|
||||
" push %%eax\n"
|
||||
" popfl\n"
|
||||
" pushfl\n"
|
||||
" pop %%eax\n"
|
||||
" xor %%ecx, %%eax\n"
|
||||
" mov %%eax, %0\n"
|
||||
" push %%ecx\n"
|
||||
" popfl"
|
||||
: "=m" (supported) // output
|
||||
: // input
|
||||
: "eax", "ecx", "memory"); // clobbered register
|
||||
|
||||
return supported != 0;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,13 +9,16 @@
|
||||
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
|
||||
class NzHardwareInfoImpl
|
||||
namespace Nz
|
||||
{
|
||||
public:
|
||||
static void Cpuid(nzUInt32 functionId, nzUInt32 subFunctionId, nzUInt32 registers[4]);
|
||||
static unsigned int GetProcessorCount();
|
||||
static nzUInt64 GetTotalMemory();
|
||||
static bool IsCpuidSupported();
|
||||
};
|
||||
class HardwareInfoImpl
|
||||
{
|
||||
public:
|
||||
static void Cpuid(UInt32 functionId, UInt32 subFunctionId, UInt32 registers[4]);
|
||||
static unsigned int GetProcessorCount();
|
||||
static UInt64 GetTotalMemory();
|
||||
static bool IsCpuidSupported();
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NAZARA_HARDWAREINFOIMPL_WINDOWS_HPP
|
||||
|
||||
@@ -5,31 +5,34 @@
|
||||
#include <Nazara/Core/Win32/MutexImpl.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzMutexImpl::NzMutexImpl()
|
||||
namespace Nz
|
||||
{
|
||||
#if NAZARA_CORE_WINDOWS_CS_SPINLOCKS > 0
|
||||
InitializeCriticalSectionAndSpinCount(&m_criticalSection, NAZARA_CORE_WINDOWS_CS_SPINLOCKS);
|
||||
#else
|
||||
InitializeCriticalSection(&m_criticalSection);
|
||||
#endif
|
||||
}
|
||||
MutexImpl::MutexImpl()
|
||||
{
|
||||
#if NAZARA_CORE_WINDOWS_CS_SPINLOCKS > 0
|
||||
InitializeCriticalSectionAndSpinCount(&m_criticalSection, NAZARA_CORE_WINDOWS_CS_SPINLOCKS);
|
||||
#else
|
||||
InitializeCriticalSection(&m_criticalSection);
|
||||
#endif
|
||||
}
|
||||
|
||||
NzMutexImpl::~NzMutexImpl()
|
||||
{
|
||||
DeleteCriticalSection(&m_criticalSection);
|
||||
}
|
||||
MutexImpl::~MutexImpl()
|
||||
{
|
||||
DeleteCriticalSection(&m_criticalSection);
|
||||
}
|
||||
|
||||
void NzMutexImpl::Lock()
|
||||
{
|
||||
EnterCriticalSection(&m_criticalSection);
|
||||
}
|
||||
void MutexImpl::Lock()
|
||||
{
|
||||
EnterCriticalSection(&m_criticalSection);
|
||||
}
|
||||
|
||||
bool NzMutexImpl::TryLock()
|
||||
{
|
||||
return TryEnterCriticalSection(&m_criticalSection) != 0;
|
||||
}
|
||||
bool MutexImpl::TryLock()
|
||||
{
|
||||
return TryEnterCriticalSection(&m_criticalSection) != 0;
|
||||
}
|
||||
|
||||
void NzMutexImpl::Unlock()
|
||||
{
|
||||
LeaveCriticalSection(&m_criticalSection);
|
||||
void MutexImpl::Unlock()
|
||||
{
|
||||
LeaveCriticalSection(&m_criticalSection);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,20 +10,23 @@
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
#include <windows.h>
|
||||
|
||||
class NzMutexImpl
|
||||
namespace Nz
|
||||
{
|
||||
friend class NzConditionVariableImpl;
|
||||
class MutexImpl
|
||||
{
|
||||
friend class ConditionVariableImpl;
|
||||
|
||||
public:
|
||||
NzMutexImpl();
|
||||
~NzMutexImpl();
|
||||
public:
|
||||
MutexImpl();
|
||||
~MutexImpl();
|
||||
|
||||
void Lock();
|
||||
bool TryLock();
|
||||
void Unlock();
|
||||
void Lock();
|
||||
bool TryLock();
|
||||
void Unlock();
|
||||
|
||||
private:
|
||||
CRITICAL_SECTION m_criticalSection;
|
||||
};
|
||||
private:
|
||||
CRITICAL_SECTION m_criticalSection;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NAZARA_MUTEXIMPL_HPP
|
||||
|
||||
@@ -8,57 +8,60 @@
|
||||
#include <limits>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzSemaphoreImpl::NzSemaphoreImpl(unsigned int count)
|
||||
namespace Nz
|
||||
{
|
||||
m_semaphore = CreateSemaphoreW(nullptr, count, std::numeric_limits<LONG>::max(), nullptr);
|
||||
if (!m_semaphore)
|
||||
NazaraError("Failed to create semaphore: " + NzError::GetLastSystemError());
|
||||
}
|
||||
|
||||
NzSemaphoreImpl::~NzSemaphoreImpl()
|
||||
{
|
||||
CloseHandle(m_semaphore);
|
||||
}
|
||||
|
||||
unsigned int NzSemaphoreImpl::GetCount() const
|
||||
{
|
||||
LONG count;
|
||||
ReleaseSemaphore(m_semaphore, 0, &count);
|
||||
return count;
|
||||
}
|
||||
|
||||
void NzSemaphoreImpl::Post()
|
||||
{
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (!ReleaseSemaphore(m_semaphore, 1, nullptr))
|
||||
NazaraError("Failed to release semaphore: " + NzError::GetLastSystemError());
|
||||
#else
|
||||
ReleaseSemaphore(m_semaphore, 1, nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
void NzSemaphoreImpl::Wait()
|
||||
{
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (WaitForSingleObject(m_semaphore, INFINITE) == WAIT_FAILED)
|
||||
NazaraError("Failed to wait for semaphore: " + NzError::GetLastSystemError());
|
||||
#else
|
||||
WaitForSingleObject(m_semaphore, INFINITE);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool NzSemaphoreImpl::Wait(nzUInt32 timeout)
|
||||
{
|
||||
#if NAZARA_CORE_SAFE
|
||||
DWORD result = WaitForSingleObject(m_semaphore, timeout);
|
||||
if (result == WAIT_FAILED)
|
||||
SemaphoreImpl::SemaphoreImpl(unsigned int count)
|
||||
{
|
||||
NazaraError("Failed to wait for semaphore: " + NzError::GetLastSystemError());
|
||||
return false;
|
||||
m_semaphore = CreateSemaphoreW(nullptr, count, std::numeric_limits<LONG>::max(), nullptr);
|
||||
if (!m_semaphore)
|
||||
NazaraError("Failed to create semaphore: " + Error::GetLastSystemError());
|
||||
}
|
||||
|
||||
SemaphoreImpl::~SemaphoreImpl()
|
||||
{
|
||||
CloseHandle(m_semaphore);
|
||||
}
|
||||
|
||||
unsigned int SemaphoreImpl::GetCount() const
|
||||
{
|
||||
LONG count;
|
||||
ReleaseSemaphore(m_semaphore, 0, &count);
|
||||
return count;
|
||||
}
|
||||
|
||||
void SemaphoreImpl::Post()
|
||||
{
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (!ReleaseSemaphore(m_semaphore, 1, nullptr))
|
||||
NazaraError("Failed to release semaphore: " + Error::GetLastSystemError());
|
||||
#else
|
||||
ReleaseSemaphore(m_semaphore, 1, nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
void SemaphoreImpl::Wait()
|
||||
{
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (WaitForSingleObject(m_semaphore, INFINITE) == WAIT_FAILED)
|
||||
NazaraError("Failed to wait for semaphore: " + Error::GetLastSystemError());
|
||||
#else
|
||||
WaitForSingleObject(m_semaphore, INFINITE);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool SemaphoreImpl::Wait(UInt32 timeout)
|
||||
{
|
||||
#if NAZARA_CORE_SAFE
|
||||
DWORD result = WaitForSingleObject(m_semaphore, timeout);
|
||||
if (result == WAIT_FAILED)
|
||||
{
|
||||
NazaraError("Failed to wait for semaphore: " + Error::GetLastSystemError());
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return result == WAIT_OBJECT_0;
|
||||
#else
|
||||
return WaitForSingleObject(m_semaphore, timeout) == WAIT_OBJECT_0;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
return result == WAIT_OBJECT_0;
|
||||
#else
|
||||
return WaitForSingleObject(m_semaphore, timeout) == WAIT_OBJECT_0;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -10,19 +10,22 @@
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
#include <windows.h>
|
||||
|
||||
class NzSemaphoreImpl
|
||||
namespace Nz
|
||||
{
|
||||
public:
|
||||
NzSemaphoreImpl(unsigned int count);
|
||||
~NzSemaphoreImpl();
|
||||
class SemaphoreImpl
|
||||
{
|
||||
public:
|
||||
SemaphoreImpl(unsigned int count);
|
||||
~SemaphoreImpl();
|
||||
|
||||
unsigned int GetCount() const;
|
||||
void Post();
|
||||
void Wait();
|
||||
bool Wait(nzUInt32 timeout);
|
||||
unsigned int GetCount() const;
|
||||
void Post();
|
||||
void Wait();
|
||||
bool Wait(UInt32 timeout);
|
||||
|
||||
private:
|
||||
HANDLE m_semaphore;
|
||||
};
|
||||
private:
|
||||
HANDLE m_semaphore;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NAZARA_SEMAPHOREIMPL_HPP
|
||||
|
||||
@@ -9,237 +9,240 @@
|
||||
#include <process.h>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
bool NzTaskSchedulerImpl::Initialize(unsigned int workerCount)
|
||||
namespace Nz
|
||||
{
|
||||
if (IsInitialized())
|
||||
return true; // Déjà initialisé
|
||||
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (workerCount == 0)
|
||||
bool TaskSchedulerImpl::Initialize(unsigned int workerCount)
|
||||
{
|
||||
NazaraError("Invalid worker count ! (0)");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
if (IsInitialized())
|
||||
return true; // Déjà initialisé
|
||||
|
||||
s_workerCount = workerCount;
|
||||
s_doneEvents.reset(new HANDLE[workerCount]);
|
||||
s_workers.reset(new Worker[workerCount]);
|
||||
s_workerThreads.reset(new HANDLE[workerCount]);
|
||||
#if NAZARA_CORE_SAFE
|
||||
if (workerCount == 0)
|
||||
{
|
||||
NazaraError("Invalid worker count ! (0)");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
// L'identifiant de chaque worker doit rester en vie jusqu'à ce que chaque thread soit correctement lancé
|
||||
std::unique_ptr<unsigned int[]> workerIDs(new unsigned int[workerCount]);
|
||||
s_workerCount = workerCount;
|
||||
s_doneEvents.reset(new HANDLE[workerCount]);
|
||||
s_workers.reset(new Worker[workerCount]);
|
||||
s_workerThreads.reset(new HANDLE[workerCount]);
|
||||
|
||||
for (unsigned int i = 0; i < workerCount; ++i)
|
||||
{
|
||||
// On initialise les évènements, mutex et threads de chaque worker
|
||||
Worker& worker = s_workers[i];
|
||||
InitializeCriticalSection(&worker.queueMutex);
|
||||
worker.wakeEvent = CreateEventW(nullptr, false, false, nullptr);
|
||||
worker.running = true;
|
||||
worker.workCount = 0;
|
||||
// L'identifiant de chaque worker doit rester en vie jusqu'à ce que chaque thread soit correctement lancé
|
||||
std::unique_ptr<unsigned int[]> workerIDs(new unsigned int[workerCount]);
|
||||
|
||||
s_doneEvents[i] = CreateEventW(nullptr, true, false, nullptr);
|
||||
for (unsigned int i = 0; i < workerCount; ++i)
|
||||
{
|
||||
// On initialise les évènements, mutex et threads de chaque worker
|
||||
Worker& worker = s_workers[i];
|
||||
InitializeCriticalSection(&worker.queueMutex);
|
||||
worker.wakeEvent = CreateEventW(nullptr, false, false, nullptr);
|
||||
worker.running = true;
|
||||
worker.workCount = 0;
|
||||
|
||||
// Le thread va se lancer, signaler qu'il est prêt à travailler (s_doneEvents) et attendre d'être réveillé
|
||||
workerIDs[i] = i;
|
||||
s_workerThreads[i] = reinterpret_cast<HANDLE>(_beginthreadex(nullptr, 0, &WorkerProc, &workerIDs[i], 0, nullptr));
|
||||
s_doneEvents[i] = CreateEventW(nullptr, true, false, nullptr);
|
||||
|
||||
// Le thread va se lancer, signaler qu'il est prêt à travailler (s_doneEvents) et attendre d'être réveillé
|
||||
workerIDs[i] = i;
|
||||
s_workerThreads[i] = reinterpret_cast<HANDLE>(_beginthreadex(nullptr, 0, &WorkerProc, &workerIDs[i], 0, nullptr));
|
||||
}
|
||||
|
||||
// On attend que les workers se mettent en attente
|
||||
WaitForMultipleObjects(s_workerCount, &s_doneEvents[0], true, INFINITE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// On attend que les workers se mettent en attente
|
||||
WaitForMultipleObjects(s_workerCount, &s_doneEvents[0], true, INFINITE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzTaskSchedulerImpl::IsInitialized()
|
||||
{
|
||||
return s_workerCount > 0;
|
||||
}
|
||||
|
||||
void NzTaskSchedulerImpl::Run(NzFunctor** tasks, unsigned int count)
|
||||
{
|
||||
// On s'assure que des tâches ne sont pas déjà en cours
|
||||
WaitForMultipleObjects(s_workerCount, &s_doneEvents[0], true, INFINITE);
|
||||
|
||||
std::ldiv_t div = std::ldiv(count, s_workerCount); // Division et modulo en une opération, y'a pas de petit profit
|
||||
for (unsigned int i = 0; i < s_workerCount; ++i)
|
||||
bool TaskSchedulerImpl::IsInitialized()
|
||||
{
|
||||
// On va maintenant répartir les tâches entre chaque worker et les envoyer dans la queue de chacun
|
||||
Worker& worker = s_workers[i];
|
||||
unsigned int taskCount = (i == 0) ? div.quot + div.rem : div.quot;
|
||||
for (unsigned int j = 0; j < taskCount; ++j)
|
||||
worker.queue.push(*tasks++);
|
||||
|
||||
// On stocke le nombre de tâches à côté dans un entier atomique pour éviter d'entrer inutilement dans une section critique
|
||||
worker.workCount = taskCount;
|
||||
return s_workerCount > 0;
|
||||
}
|
||||
|
||||
// On les lance une fois qu'ils sont tous initialisés (pour éviter qu'un worker ne passe en pause détectant une absence de travaux)
|
||||
for (unsigned int i = 0; i < s_workerCount; ++i)
|
||||
void TaskSchedulerImpl::Run(Functor** tasks, unsigned int count)
|
||||
{
|
||||
ResetEvent(s_doneEvents[i]);
|
||||
SetEvent(s_workers[i].wakeEvent);
|
||||
}
|
||||
}
|
||||
// On s'assure que des tâches ne sont pas déjà en cours
|
||||
WaitForMultipleObjects(s_workerCount, &s_doneEvents[0], true, INFINITE);
|
||||
|
||||
void NzTaskSchedulerImpl::Uninitialize()
|
||||
{
|
||||
#ifdef NAZARA_CORE_SAFE
|
||||
if (s_workerCount == 0)
|
||||
{
|
||||
NazaraError("Task scheduler is not initialized");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// On commence par vider la queue de chaque worker pour s'assurer qu'ils s'arrêtent
|
||||
for (unsigned int i = 0; i < s_workerCount; ++i)
|
||||
{
|
||||
Worker& worker = s_workers[i];
|
||||
worker.running = false;
|
||||
worker.workCount = 0;
|
||||
|
||||
EnterCriticalSection(&worker.queueMutex);
|
||||
|
||||
std::queue<NzFunctor*> emptyQueue;
|
||||
std::swap(worker.queue, emptyQueue); // Et on vide la queue (merci std::swap)
|
||||
|
||||
LeaveCriticalSection(&worker.queueMutex);
|
||||
|
||||
// On réveille le worker pour qu'il sorte de la boucle et termine le thread
|
||||
SetEvent(worker.wakeEvent);
|
||||
}
|
||||
|
||||
// On attend que chaque thread se termine
|
||||
WaitForMultipleObjects(s_workerCount, &s_workerThreads[0], true, INFINITE);
|
||||
|
||||
// Et on libère les ressources
|
||||
for (unsigned int i = 0; i < s_workerCount; ++i)
|
||||
{
|
||||
Worker& worker = s_workers[i];
|
||||
CloseHandle(s_doneEvents[i]);
|
||||
CloseHandle(s_workerThreads[i]);
|
||||
CloseHandle(worker.wakeEvent);
|
||||
DeleteCriticalSection(&worker.queueMutex);
|
||||
}
|
||||
|
||||
s_doneEvents.reset();
|
||||
s_workers.reset();
|
||||
s_workerThreads.reset();
|
||||
s_workerCount = 0;
|
||||
}
|
||||
|
||||
void NzTaskSchedulerImpl::WaitForTasks()
|
||||
{
|
||||
#ifdef NAZARA_CORE_SAFE
|
||||
if (s_workerCount == 0)
|
||||
{
|
||||
NazaraError("Task scheduler is not initialized");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
WaitForMultipleObjects(s_workerCount, &s_doneEvents[0], true, INFINITE);
|
||||
}
|
||||
|
||||
NzFunctor* NzTaskSchedulerImpl::StealTask(unsigned int workerID)
|
||||
{
|
||||
bool shouldRetry;
|
||||
do
|
||||
{
|
||||
shouldRetry = false;
|
||||
std::ldiv_t div = std::ldiv(count, s_workerCount); // Division et modulo en une opération, y'a pas de petit profit
|
||||
for (unsigned int i = 0; i < s_workerCount; ++i)
|
||||
{
|
||||
// On ne vole pas la famille, ni soi-même.
|
||||
if (i == workerID)
|
||||
continue;
|
||||
|
||||
// On va maintenant répartir les tâches entre chaque worker et les envoyer dans la queue de chacun
|
||||
Worker& worker = s_workers[i];
|
||||
unsigned int taskCount = (i == 0) ? div.quot + div.rem : div.quot;
|
||||
for (unsigned int j = 0; j < taskCount; ++j)
|
||||
worker.queue.push(*tasks++);
|
||||
|
||||
// Ce worker a-t-il encore des tâches dans sa file d'attente ?
|
||||
if (worker.workCount > 0)
|
||||
{
|
||||
NzFunctor* task = nullptr;
|
||||
// On stocke le nombre de tâches à côté dans un entier atomique pour éviter d'entrer inutilement dans une section critique
|
||||
worker.workCount = taskCount;
|
||||
}
|
||||
|
||||
// Est-ce qu'il utilise la queue maintenant ?
|
||||
if (TryEnterCriticalSection(&worker.queueMutex))
|
||||
{
|
||||
// Non, super ! Profitons-en pour essayer de lui voler un job
|
||||
if (!worker.queue.empty()) // On vérifie que la queue n'est pas vide (peut avoir changé avant le verrouillage)
|
||||
{
|
||||
// Et hop, on vole la tâche
|
||||
task = worker.queue.front();
|
||||
worker.queue.pop();
|
||||
worker.workCount = worker.queue.size();
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&worker.queueMutex);
|
||||
}
|
||||
else
|
||||
shouldRetry = true; // Il est encore possible d'avoir un job
|
||||
|
||||
// Avons-nous notre tâche ?
|
||||
if (task)
|
||||
return task; // Parfait, sortons de là !
|
||||
}
|
||||
// On les lance une fois qu'ils sont tous initialisés (pour éviter qu'un worker ne passe en pause détectant une absence de travaux)
|
||||
for (unsigned int i = 0; i < s_workerCount; ++i)
|
||||
{
|
||||
ResetEvent(s_doneEvents[i]);
|
||||
SetEvent(s_workers[i].wakeEvent);
|
||||
}
|
||||
}
|
||||
while (shouldRetry);
|
||||
|
||||
// Bon à priori plus aucun worker n'a de tâche
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
unsigned int __stdcall NzTaskSchedulerImpl::WorkerProc(void* userdata)
|
||||
{
|
||||
unsigned int workerID = *reinterpret_cast<unsigned int*>(userdata);
|
||||
SetEvent(s_doneEvents[workerID]);
|
||||
|
||||
Worker& worker = s_workers[workerID];
|
||||
WaitForSingleObject(worker.wakeEvent, INFINITE);
|
||||
|
||||
while (worker.running)
|
||||
void TaskSchedulerImpl::Uninitialize()
|
||||
{
|
||||
NzFunctor* task = nullptr;
|
||||
|
||||
if (worker.workCount > 0) // Permet d'éviter d'entrer inutilement dans une section critique
|
||||
#ifdef NAZARA_CORE_SAFE
|
||||
if (s_workerCount == 0)
|
||||
{
|
||||
NazaraError("Task scheduler is not initialized");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// On commence par vider la queue de chaque worker pour s'assurer qu'ils s'arrêtent
|
||||
for (unsigned int i = 0; i < s_workerCount; ++i)
|
||||
{
|
||||
Worker& worker = s_workers[i];
|
||||
worker.running = false;
|
||||
worker.workCount = 0;
|
||||
|
||||
EnterCriticalSection(&worker.queueMutex);
|
||||
if (!worker.queue.empty()) // Nécessaire car le workCount peut être tombé à zéro juste avant l'entrée dans la section critique
|
||||
{
|
||||
task = worker.queue.front();
|
||||
worker.queue.pop();
|
||||
worker.workCount = worker.queue.size();
|
||||
}
|
||||
|
||||
std::queue<Functor*> emptyQueue;
|
||||
std::swap(worker.queue, emptyQueue); // Et on vide la queue (merci std::swap)
|
||||
|
||||
LeaveCriticalSection(&worker.queueMutex);
|
||||
|
||||
// On réveille le worker pour qu'il sorte de la boucle et termine le thread
|
||||
SetEvent(worker.wakeEvent);
|
||||
}
|
||||
|
||||
// Que faire quand vous n'avez plus de travail ?
|
||||
if (!task)
|
||||
task = StealTask(workerID); // Voler le travail des autres !
|
||||
// On attend que chaque thread se termine
|
||||
WaitForMultipleObjects(s_workerCount, &s_workerThreads[0], true, INFINITE);
|
||||
|
||||
if (task)
|
||||
// Et on libère les ressources
|
||||
for (unsigned int i = 0; i < s_workerCount; ++i)
|
||||
{
|
||||
// On exécute la tâche avant de la supprimer
|
||||
task->Run();
|
||||
delete task;
|
||||
}
|
||||
else
|
||||
{
|
||||
SetEvent(s_doneEvents[workerID]);
|
||||
WaitForSingleObject(worker.wakeEvent, INFINITE);
|
||||
Worker& worker = s_workers[i];
|
||||
CloseHandle(s_doneEvents[i]);
|
||||
CloseHandle(s_workerThreads[i]);
|
||||
CloseHandle(worker.wakeEvent);
|
||||
DeleteCriticalSection(&worker.queueMutex);
|
||||
}
|
||||
|
||||
s_doneEvents.reset();
|
||||
s_workers.reset();
|
||||
s_workerThreads.reset();
|
||||
s_workerCount = 0;
|
||||
}
|
||||
|
||||
// Au cas où un thread attendrait sur WaitForTasks() pendant qu'un autre appellerait Uninitialize()
|
||||
// Ça ne devrait pas arriver, mais comme ça ne coûte pas grand chose..
|
||||
SetEvent(s_doneEvents[workerID]);
|
||||
void TaskSchedulerImpl::WaitForTasks()
|
||||
{
|
||||
#ifdef NAZARA_CORE_SAFE
|
||||
if (s_workerCount == 0)
|
||||
{
|
||||
NazaraError("Task scheduler is not initialized");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
WaitForMultipleObjects(s_workerCount, &s_doneEvents[0], true, INFINITE);
|
||||
}
|
||||
|
||||
Functor* TaskSchedulerImpl::StealTask(unsigned int workerID)
|
||||
{
|
||||
bool shouldRetry;
|
||||
do
|
||||
{
|
||||
shouldRetry = false;
|
||||
for (unsigned int i = 0; i < s_workerCount; ++i)
|
||||
{
|
||||
// On ne vole pas la famille, ni soi-même.
|
||||
if (i == workerID)
|
||||
continue;
|
||||
|
||||
Worker& worker = s_workers[i];
|
||||
|
||||
// Ce worker a-t-il encore des tâches dans sa file d'attente ?
|
||||
if (worker.workCount > 0)
|
||||
{
|
||||
Functor* task = nullptr;
|
||||
|
||||
// Est-ce qu'il utilise la queue maintenant ?
|
||||
if (TryEnterCriticalSection(&worker.queueMutex))
|
||||
{
|
||||
// Non, super ! Profitons-en pour essayer de lui voler un job
|
||||
if (!worker.queue.empty()) // On vérifie que la queue n'est pas vide (peut avoir changé avant le verrouillage)
|
||||
{
|
||||
// Et hop, on vole la tâche
|
||||
task = worker.queue.front();
|
||||
worker.queue.pop();
|
||||
worker.workCount = worker.queue.size();
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&worker.queueMutex);
|
||||
}
|
||||
else
|
||||
shouldRetry = true; // Il est encore possible d'avoir un job
|
||||
|
||||
// Avons-nous notre tâche ?
|
||||
if (task)
|
||||
return task; // Parfait, sortons de là !
|
||||
}
|
||||
}
|
||||
}
|
||||
while (shouldRetry);
|
||||
|
||||
// Bon à priori plus aucun worker n'a de tâche
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
unsigned int __stdcall TaskSchedulerImpl::WorkerProc(void* userdata)
|
||||
{
|
||||
unsigned int workerID = *reinterpret_cast<unsigned int*>(userdata);
|
||||
SetEvent(s_doneEvents[workerID]);
|
||||
|
||||
Worker& worker = s_workers[workerID];
|
||||
WaitForSingleObject(worker.wakeEvent, INFINITE);
|
||||
|
||||
while (worker.running)
|
||||
{
|
||||
Functor* task = nullptr;
|
||||
|
||||
if (worker.workCount > 0) // Permet d'éviter d'entrer inutilement dans une section critique
|
||||
{
|
||||
EnterCriticalSection(&worker.queueMutex);
|
||||
if (!worker.queue.empty()) // Nécessaire car le workCount peut être tombé à zéro juste avant l'entrée dans la section critique
|
||||
{
|
||||
task = worker.queue.front();
|
||||
worker.queue.pop();
|
||||
worker.workCount = worker.queue.size();
|
||||
}
|
||||
LeaveCriticalSection(&worker.queueMutex);
|
||||
}
|
||||
|
||||
// Que faire quand vous n'avez plus de travail ?
|
||||
if (!task)
|
||||
task = StealTask(workerID); // Voler le travail des autres !
|
||||
|
||||
if (task)
|
||||
{
|
||||
// On exécute la tâche avant de la supprimer
|
||||
task->Run();
|
||||
delete task;
|
||||
}
|
||||
else
|
||||
{
|
||||
SetEvent(s_doneEvents[workerID]);
|
||||
WaitForSingleObject(worker.wakeEvent, INFINITE);
|
||||
}
|
||||
}
|
||||
|
||||
// Au cas où un thread attendrait sur WaitForTasks() pendant qu'un autre appellerait Uninitialize()
|
||||
// Ça ne devrait pas arriver, mais comme ça ne coûte pas grand chose..
|
||||
SetEvent(s_doneEvents[workerID]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::unique_ptr<HANDLE[]> TaskSchedulerImpl::s_doneEvents; // Doivent être contigus
|
||||
std::unique_ptr<TaskSchedulerImpl::Worker[]> TaskSchedulerImpl::s_workers;
|
||||
std::unique_ptr<HANDLE[]> TaskSchedulerImpl::s_workerThreads; // Doivent être contigus
|
||||
unsigned int TaskSchedulerImpl::s_workerCount;
|
||||
}
|
||||
|
||||
std::unique_ptr<HANDLE[]> NzTaskSchedulerImpl::s_doneEvents; // Doivent être contigus
|
||||
std::unique_ptr<NzTaskSchedulerImpl::Worker[]> NzTaskSchedulerImpl::s_workers;
|
||||
std::unique_ptr<HANDLE[]> NzTaskSchedulerImpl::s_workerThreads; // Doivent être contigus
|
||||
unsigned int NzTaskSchedulerImpl::s_workerCount;
|
||||
|
||||
@@ -14,35 +14,38 @@
|
||||
#include <queue>
|
||||
#include <windows.h>
|
||||
|
||||
class NzTaskSchedulerImpl
|
||||
namespace Nz
|
||||
{
|
||||
public:
|
||||
NzTaskSchedulerImpl() = delete;
|
||||
~NzTaskSchedulerImpl() = delete;
|
||||
class TaskSchedulerImpl
|
||||
{
|
||||
public:
|
||||
TaskSchedulerImpl() = delete;
|
||||
~TaskSchedulerImpl() = delete;
|
||||
|
||||
static bool Initialize(unsigned int workerCount);
|
||||
static bool IsInitialized();
|
||||
static void Run(NzFunctor** tasks, unsigned int count);
|
||||
static void Uninitialize();
|
||||
static void WaitForTasks();
|
||||
static bool Initialize(unsigned int workerCount);
|
||||
static bool IsInitialized();
|
||||
static void Run(Functor** tasks, unsigned int count);
|
||||
static void Uninitialize();
|
||||
static void WaitForTasks();
|
||||
|
||||
private:
|
||||
static NzFunctor* StealTask(unsigned int workerID);
|
||||
static unsigned int __stdcall WorkerProc(void* userdata);
|
||||
private:
|
||||
static Functor* StealTask(unsigned int workerID);
|
||||
static unsigned int __stdcall WorkerProc(void* userdata);
|
||||
|
||||
struct Worker
|
||||
{
|
||||
std::atomic_uint workCount;
|
||||
std::queue<NzFunctor*> queue;
|
||||
CRITICAL_SECTION queueMutex;
|
||||
HANDLE wakeEvent;
|
||||
volatile bool running;
|
||||
};
|
||||
struct Worker
|
||||
{
|
||||
std::atomic_uint workCount;
|
||||
std::queue<Functor*> queue;
|
||||
CRITICAL_SECTION queueMutex;
|
||||
HANDLE wakeEvent;
|
||||
volatile bool running;
|
||||
};
|
||||
|
||||
static std::unique_ptr<HANDLE[]> s_doneEvents; // Doivent être contigus
|
||||
static std::unique_ptr<Worker[]> s_workers;
|
||||
static std::unique_ptr<HANDLE[]> s_workerThreads; // Doivent être contigus
|
||||
static unsigned int s_workerCount;
|
||||
static std::unique_ptr<HANDLE[]> s_doneEvents; // Doivent être contigus
|
||||
static std::unique_ptr<Worker[]> s_workers;
|
||||
static std::unique_ptr<HANDLE[]> s_workerThreads; // Doivent être contigus
|
||||
static unsigned int s_workerCount;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NAZARA_TASKSCHEDULERIMPL_HPP
|
||||
|
||||
@@ -8,40 +8,43 @@
|
||||
#include <process.h>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
NzThreadImpl::NzThreadImpl(NzFunctor* functor)
|
||||
namespace Nz
|
||||
{
|
||||
m_handle = reinterpret_cast<HANDLE>(_beginthreadex(nullptr, 0, &NzThreadImpl::ThreadProc, functor, 0, nullptr));
|
||||
if (!m_handle)
|
||||
NazaraInternalError("Failed to create thread: " + NzError::GetLastSystemError());
|
||||
}
|
||||
|
||||
void NzThreadImpl::Detach()
|
||||
{
|
||||
// http://stackoverflow.com/questions/418742/is-it-reasonable-to-call-closehandle-on-a-thread-before-it-terminates
|
||||
CloseHandle(m_handle);
|
||||
}
|
||||
|
||||
void NzThreadImpl::Join()
|
||||
{
|
||||
WaitForSingleObject(m_handle, INFINITE);
|
||||
CloseHandle(m_handle);
|
||||
}
|
||||
|
||||
unsigned int __stdcall NzThreadImpl::ThreadProc(void* userdata)
|
||||
{
|
||||
NzFunctor* func = static_cast<NzFunctor*>(userdata);
|
||||
func->Run();
|
||||
delete func;
|
||||
|
||||
/*
|
||||
En C++, il vaut mieux retourner depuis la fonction que de quitter le thread explicitement
|
||||
Source : http://msdn.microsoft.com/en-us/library/windows/desktop/ms682659(v=vs.85).aspx
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void NzThreadImpl::Sleep(nzUInt32 time)
|
||||
{
|
||||
::Sleep(time);
|
||||
ThreadImpl::ThreadImpl(Functor* functor)
|
||||
{
|
||||
m_handle = reinterpret_cast<HANDLE>(_beginthreadex(nullptr, 0, &ThreadImpl::ThreadProc, functor, 0, nullptr));
|
||||
if (!m_handle)
|
||||
NazaraInternalError("Failed to create thread: " + Error::GetLastSystemError());
|
||||
}
|
||||
|
||||
void ThreadImpl::Detach()
|
||||
{
|
||||
// http://stackoverflow.com/questions/418742/is-it-reasonable-to-call-closehandle-on-a-thread-before-it-terminates
|
||||
CloseHandle(m_handle);
|
||||
}
|
||||
|
||||
void ThreadImpl::Join()
|
||||
{
|
||||
WaitForSingleObject(m_handle, INFINITE);
|
||||
CloseHandle(m_handle);
|
||||
}
|
||||
|
||||
unsigned int __stdcall ThreadImpl::ThreadProc(void* userdata)
|
||||
{
|
||||
Functor* func = static_cast<Functor*>(userdata);
|
||||
func->Run();
|
||||
delete func;
|
||||
|
||||
/*
|
||||
En C++, il vaut mieux retourner depuis la fonction que de quitter le thread explicitement
|
||||
Source : http://msdn.microsoft.com/en-us/library/windows/desktop/ms682659(v=vs.85).aspx
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ThreadImpl::Sleep(UInt32 time)
|
||||
{
|
||||
::Sleep(time);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,22 +12,25 @@
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
#include <windows.h>
|
||||
|
||||
struct NzFunctor;
|
||||
|
||||
class NzThreadImpl
|
||||
namespace Nz
|
||||
{
|
||||
public:
|
||||
NzThreadImpl(NzFunctor* threadFunc);
|
||||
struct Functor;
|
||||
|
||||
void Detach();
|
||||
void Join();
|
||||
class ThreadImpl
|
||||
{
|
||||
public:
|
||||
ThreadImpl(Functor* threadFunc);
|
||||
|
||||
static void Sleep(nzUInt32 time);
|
||||
void Detach();
|
||||
void Join();
|
||||
|
||||
private:
|
||||
static unsigned int __stdcall ThreadProc(void* userdata);
|
||||
static void Sleep(UInt32 time);
|
||||
|
||||
HANDLE m_handle;
|
||||
};
|
||||
private:
|
||||
static unsigned int __stdcall ThreadProc(void* userdata);
|
||||
|
||||
HANDLE m_handle;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // NAZARA_THREADIMPL_HPP
|
||||
|
||||
@@ -5,21 +5,24 @@
|
||||
#include <Nazara/Core/Win32/Time.hpp>
|
||||
#include <Nazara/Core/Debug.hpp>
|
||||
|
||||
time_t NzFileTimeToTime(FILETIME* time)
|
||||
namespace Nz
|
||||
{
|
||||
SYSTEMTIME stUTC, stLocal;
|
||||
time_t FileTimeToTime(FILETIME* time)
|
||||
{
|
||||
SYSTEMTIME stUTC, stLocal;
|
||||
|
||||
FileTimeToSystemTime(time, &stUTC);
|
||||
SystemTimeToTzSpecificLocalTime(nullptr, &stUTC, &stLocal);
|
||||
FileTimeToSystemTime(time, &stUTC);
|
||||
SystemTimeToTzSpecificLocalTime(nullptr, &stUTC, &stLocal);
|
||||
|
||||
std::tm timeinfo;
|
||||
timeinfo.tm_sec = stLocal.wSecond;
|
||||
timeinfo.tm_min = stLocal.wMinute;
|
||||
timeinfo.tm_hour = stLocal.wHour;
|
||||
timeinfo.tm_mday = stLocal.wDay;
|
||||
timeinfo.tm_mon = stLocal.wMonth-1;
|
||||
timeinfo.tm_year = stLocal.wYear-1900;
|
||||
timeinfo.tm_isdst = -1;
|
||||
std::tm timeinfo;
|
||||
timeinfo.tm_sec = stLocal.wSecond;
|
||||
timeinfo.tm_min = stLocal.wMinute;
|
||||
timeinfo.tm_hour = stLocal.wHour;
|
||||
timeinfo.tm_mday = stLocal.wDay;
|
||||
timeinfo.tm_mon = stLocal.wMonth-1;
|
||||
timeinfo.tm_year = stLocal.wYear-1900;
|
||||
timeinfo.tm_isdst = -1;
|
||||
|
||||
return std::mktime(&timeinfo);
|
||||
return std::mktime(&timeinfo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
#include <ctime>
|
||||
#include <windows.h>
|
||||
|
||||
time_t NzFileTimeToTime(FILETIME* time);
|
||||
namespace Nz
|
||||
{
|
||||
time_t FileTimeToTime(FILETIME* time);
|
||||
}
|
||||
|
||||
#endif // NAZARA_WINDOWS_TIME_HPP
|
||||
|
||||
Reference in New Issue
Block a user