Switch from Nz prefix to namespace Nz

What a huge commit


Former-commit-id: 38ac5eebf70adc1180f571f6006192d28fb99897
This commit is contained in:
Lynix
2015-09-25 19:20:05 +02:00
parent c214251ecf
commit df8da275c4
609 changed files with 68265 additions and 66534 deletions

View File

@@ -5,4 +5,7 @@
#include <Nazara/Core/AbstractHash.hpp>
#include <Nazara/Core/Debug.hpp>
NzAbstractHash::~NzAbstractHash() = default;
namespace Nz
{
AbstractHash::~AbstractHash() = default;
}

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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);
}
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -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 &currentFile[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 &currentFile[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;
}
}

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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();
}
}

View File

@@ -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, &registers[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, &registers[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;
}
}

View File

@@ -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();
}
}
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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 */

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -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;

View File

@@ -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);
}
}

View File

@@ -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;
}

View File

@@ -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();
}
}

View File

@@ -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(&currentTime));
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(&currentTime));
}
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;
}
}

View File

@@ -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(&currentTime));
}
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(&currentTime));
}
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);
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}
}

View File

@@ -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>(&parameter.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>(&parameter.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(&parameter, &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>(&parameter.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>(&parameter.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>(&parameter.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(&parameter, &it->second, sizeof(Parameter));
break;
case ParameterType_String:
parameter.type = ParameterType_String;
PlacementNew<String>(&parameter.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;
}
}
}

View File

@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -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();
}
}

View File

@@ -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);
}
}

View File

@@ -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)
{
}

View File

@@ -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

View File

@@ -5,4 +5,7 @@
#include <Nazara/Core/Updatable.hpp>
#include <Nazara/Core/Debug.hpp>
NzUpdatable::~NzUpdatable() = default;
namespace Nz
{
Updatable::~Updatable() = default;
}

View File

@@ -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
}
}

View File

@@ -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

View File

@@ -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
}
}

View File

@@ -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

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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;
}
}
}

View File

@@ -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

View File

@@ -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
}
}

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -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
}

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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