Big f***ing cleanup part 1

This commit is contained in:
Lynix
2020-02-23 00:42:22 +01:00
parent 67d0e0a689
commit 3d22321109
178 changed files with 2190 additions and 5113 deletions

View File

@@ -12,12 +12,6 @@
#error OS not handled
#endif
#if NAZARA_CORE_THREADSAFE && NAZARA_THREADSAFETY_CLOCK
#include <Nazara/Core/ThreadSafety.hpp>
#else
#include <Nazara/Core/ThreadSafetyOff.hpp>
#endif
#include <Nazara/Core/Debug.hpp>
namespace Nz
@@ -78,8 +72,6 @@ namespace Nz
*/
UInt64 Clock::GetMicroseconds() const
{
NazaraLock(m_mutex);
UInt64 elapsedMicroseconds = m_elapsedTime;
if (!m_paused)
elapsedMicroseconds += (GetElapsedMicroseconds() - m_refTime);
@@ -106,8 +98,6 @@ namespace Nz
*/
bool Clock::IsPaused() const
{
NazaraLock(m_mutex);
return m_paused;
}
@@ -121,8 +111,6 @@ namespace Nz
*/
void Clock::Pause()
{
NazaraLock(m_mutex);
if (!m_paused)
{
m_elapsedTime += GetElapsedMicroseconds() - m_refTime;
@@ -139,8 +127,6 @@ namespace Nz
*/
UInt64 Clock::Restart()
{
NazaraLock(m_mutex);
Nz::UInt64 now = GetElapsedMicroseconds();
Nz::UInt64 elapsedTime = m_elapsedTime;
@@ -164,8 +150,6 @@ namespace Nz
*/
void Clock::Unpause()
{
NazaraLock(m_mutex);
if (m_paused)
{
m_refTime = GetElapsedMicroseconds();

View File

@@ -1,105 +0,0 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/ConditionVariable.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/Mutex.hpp>
#if defined(NAZARA_PLATFORM_WINDOWS)
#include <Nazara/Core/Win32/ConditionVariableImpl.hpp>
#elif defined(NAZARA_PLATFORM_POSIX)
#include <Nazara/Core/Posix/ConditionVariableImpl.hpp>
#else
#error Condition variable has no implementation
#endif
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
/*!
* \ingroup core
* \class Nz::ConditionVariable
* \brief Core class that represents a condition variable
*
* The ConditionVariable class is a synchronization primitive that can be used to block a thread, or multiple threads at the same time, until another thread both modifies a shared variable (the condition), and notifies the ConditionVariable
*/
/*!
* \brief Constructs a ConditionVariable object by default
*/
ConditionVariable::ConditionVariable()
{
m_impl = new ConditionVariableImpl;
}
/*!
* \brief Destructs the object
*/
ConditionVariable::~ConditionVariable()
{
delete m_impl;
}
/*!
* \brief Sends a signal to one thread waiting on the condition
*
* If any threads are waiting on *this, calling Signal unblocks one of the waiting threads
*
* \see SignalAll
*/
void ConditionVariable::Signal()
{
m_impl->Signal();
}
/*!
* \brief Sends a signal to every threads waiting on the condition
*
* Unblocks all threads currently waiting for *this
*
* \see Signal
*/
void ConditionVariable::SignalAll()
{
m_impl->SignalAll();
}
/*!
* \brief Makes the thread wait on the condition
*
* Wait causes the current thread to block until the condition variable is notified or a spurious wakeup occurs
*
* \param mutex Mutex for the condition
*
* \remark Produces a NazaraAssert if mutex is invalid
*/
void ConditionVariable::Wait(Mutex* mutex)
{
NazaraAssert(mutex != nullptr, "Mutex must be valid");
m_impl->Wait(mutex->m_impl);
}
/*!
* \brief Makes the thread wait on the condition for a certain amount of time
*
* Wait causes the current thread to block until the condition variable is notified, a specific time is reached, or a spurious wakeup occurs
*
* \param mutex Mutex for the condition
* \param timeout Time before expiration of the waiting
*
* \remark Produces a NazaraAssert if mutex is invalid
*/
bool ConditionVariable::Wait(Mutex* mutex, UInt32 timeout)
{
NazaraAssert(mutex != nullptr, "Mutex must be valid");
return m_impl->Wait(mutex->m_impl, timeout);
}
}

View File

@@ -1,535 +0,0 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Directory.hpp>
#include <Nazara/Core/Config.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/File.hpp>
#include <cstddef>
#include <cstring>
#include <string>
#if defined(NAZARA_PLATFORM_WINDOWS)
#include <Nazara/Core/Win32/DirectoryImpl.hpp>
#elif defined(NAZARA_PLATFORM_POSIX)
#include <Nazara/Core/Posix/DirectoryImpl.hpp>
#else
#error OS not handled
#endif
#if NAZARA_CORE_THREADSAFE && NAZARA_THREADSAFETY_DIRECTORY
#include <Nazara/Core/ThreadSafety.hpp>
#else
#include <Nazara/Core/ThreadSafetyOff.hpp>
#endif
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
namespace
{
//FIXME: MinGW seems to dislike thread_local shared_ptr.. (using a std::string is a working hackfix)
thread_local std::string currentPath(DirectoryImpl::GetCurrent().ToStdString());
}
/*!
* \ingroup core
* \class Nz::Directory
* \brief Core class that represents a directory
*/
/*!
* \brief Constructs a Directory object by default
*/
Directory::Directory() :
m_pattern('*'),
m_impl(nullptr)
{
}
/*!
* \brief Constructs a Directory object with a path
*
* \param dirPath Path to the directory
*/
Directory::Directory(const String& dirPath) :
m_dirPath(dirPath),
m_pattern('*'),
m_impl(nullptr)
{
}
/*!
* \brief Destructs the object and calls Close
*
* \see Close
*/
Directory::~Directory()
{
Close();
}
/*!
* \brief Closes the directory
*/
void Directory::Close()
{
NazaraLock(m_mutex);
if (m_impl)
{
m_impl->Close();
delete m_impl;
m_impl = nullptr;
}
}
/*!
* \brief Checks whether the directory exists
* \return true if directory exists
*/
bool Directory::Exists() const
{
NazaraLock(m_mutex);
if (IsOpen())
return true; // If directory is open, then it exists
else
return Exists(m_dirPath);
}
/*!
* \brief Gets the path of the directory
* \return Path of the directory
*/
String Directory::GetPath() const
{
NazaraLock(m_mutex);
return m_dirPath;
}
/*!
* \brief Gets the pattern for the path of the directory
* \return Pattern for the path of the directory
*/
String Directory::GetPattern() const
{
NazaraLock(m_mutex);
return m_pattern;
}
/*!
* \brief Gets the result name of the directory
* \return Resulting name
*
* \remark Produces a NazaraError if directory is not open with NAZARA_CORE_SAFE defined
*/
String Directory::GetResultName() const
{
NazaraLock(m_mutex);
#if NAZARA_CORE_SAFE
if (!IsOpen())
{
NazaraError("Directory not opened");
return String();
}
#endif
return m_impl->GetResultName();
}
/*!
* \brief Gets the result path of the directory
* \return Resulting path
*
* \remark Produces a NazaraError if directory is not open with NAZARA_CORE_SAFE defined
*/
String Directory::GetResultPath() const
{
NazaraLock(m_mutex);
#if NAZARA_CORE_SAFE
if (!IsOpen())
{
NazaraError("Directory not opened");
return String();
}
#endif
return m_dirPath + NAZARA_DIRECTORY_SEPARATOR + m_impl->GetResultName();
}
/*!
* \brief Gets the resulting size of the directory
* \return Size of the directory
*
* \remark Produces a NazaraError if directory is not open with NAZARA_CORE_SAFE defined
*/
UInt64 Directory::GetResultSize() const
{
NazaraLock(m_mutex);
#if NAZARA_CORE_SAFE
if (!IsOpen())
{
NazaraError("Directory not opened");
return 0;
}
#endif
return m_impl->GetResultSize();
}
/*!
* \brief Checks whether the directory is open
* \return true if open
*/
bool Directory::IsOpen() const
{
NazaraLock(m_mutex);
return m_impl != nullptr;
}
/*!
* \brief Checks whether the directory is result
* \return true if result
*
* \remark Produces a NazaraError if directory is not open with NAZARA_CORE_SAFE defined
*/
bool Directory::IsResultDirectory() const
{
NazaraLock(m_mutex);
#if NAZARA_CORE_SAFE
if (!IsOpen())
{
NazaraError("Directory not opened");
return false;
}
#endif
return m_impl->IsResultDirectory();
}
/*!
* \brief Sets the next result in the directory
* \return true if directory has a next result
*
* \param skipDots Skips the dots in the path
*
* \remark Produces a NazaraError if directory is not open with NAZARA_CORE_SAFE defined
*/
bool Directory::NextResult(bool skipDots)
{
NazaraLock(m_mutex);
#if NAZARA_CORE_SAFE
if (!IsOpen())
{
NazaraError("Directory not opened");
return false;
}
#endif
String name;
for (;;)
{
if (!m_impl->NextResult())
return false;
name = m_impl->GetResultName();
if (skipDots && (name == '.' || name == ".."))
continue;
if (name.Match(m_pattern))
break;
}
return true;
}
/*!
* \brief Opens the directory
* \return true if opening is successful
*/
bool Directory::Open()
{
NazaraLock(m_mutex);
Close();
if (!Exists(m_dirPath))
return false;
m_impl = new DirectoryImpl(this);
if (!m_impl->Open(m_dirPath))
{
delete m_impl;
m_impl = nullptr;
return false;
}
return true;
}
/*!
* \brief Sets the path of the directory
*
* \param dirPath Path of the directory
*/
void Directory::SetPath(const String& dirPath)
{
NazaraLock(m_mutex);
Close();
m_dirPath = File::AbsolutePath(dirPath);
}
/*!
* \brief Sets the pattern of the directory
*
* \param pattern Pattern of the directory
*/
void Directory::SetPattern(const String& pattern)
{
NazaraLock(m_mutex);
m_pattern = pattern;
}
/*!
* \brief Copies the first directory to a new directory path
* \return true if copy is successful
*
* \param sourcePath Path of the original directory
* \param destPath Path of the copied directory
*
* \remark Produces a NazaraError if could not create destination directory
* \remark Produces a NazaraError if could not open origin directory
* \remark Produces a NazaraError if could not copy a file
*/
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())
{
NazaraError("Unable to open \"" + destPath + '"');
return false;
}
while (dir.NextResult(true))
{
if (dir.IsResultDirectory())
{
if (!Copy(dir.GetResultPath(), dest + NAZARA_DIRECTORY_SEPARATOR + dir.GetResultName()))
return false;
}
else if (!File::Copy(dir.GetResultPath(), dest + NAZARA_DIRECTORY_SEPARATOR + dir.GetResultName()))
{
NazaraError("Failed to copy \"" + dir.GetResultPath() + "\" to \"" + dest + NAZARA_DIRECTORY_SEPARATOR + dir.GetResultName() + '"');
return false;
}
}
dir.Close();
return true;
}
/*!
* \brief Creates a directory from a path
* \return true if creation is successful
*
* \param dirPath Path of the directory
* \param recursive Creates subdirectories
*/
bool Directory::Create(const String& dirPath, bool recursive)
{
if (dirPath.IsEmpty())
return false;
if (recursive)
{
String path = File::NormalizePath(dirPath);
std::size_t foundPos = path.Find(NAZARA_DIRECTORY_SEPARATOR);
if (foundPos == String::npos)
return false;
#ifdef NAZARA_PLATFORM_WINDOWS
// Unlike to disk (Ex: "C:"), the network path is not considered as a directory (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
for (;;)
{
String p = path.SubString(0, foundPos);
if (p.EndsWith(NAZARA_DIRECTORY_SEPARATOR))
p = p.SubString(0, -2);
if (!p.IsEmpty())
{
if (!DirectoryImpl::Exists(p) && !DirectoryImpl::Create(p))
return false;
if (foundPos == String::npos)
break;
}
foundPos = path.Find(NAZARA_DIRECTORY_SEPARATOR, foundPos + 1);
}
return true;
}
else
return DirectoryImpl::Create(File::NormalizePath(dirPath));
}
/*!
* \brief Checks whether the directory exists
* \return true if directory exists
*
* \param dirPath Path of the directory
*/
bool Directory::Exists(const String& dirPath)
{
if (dirPath.IsEmpty())
return false;
return DirectoryImpl::Exists(File::NormalizePath(dirPath));
}
/*!
* \brief Gets the current path of this directory
* \return Current path
*/
String Directory::GetCurrent()
{
return currentPath;
}
/*!
* \brief Gets this current file relative to the engine
* \return Path to this file
*/
const char* Directory::GetCurrentFileRelativeToEngine(const char* currentFile)
{
///FIXME: Is this method in the right place ?
const char* ptr = std::strstr(currentFile, "NazaraEngine/");
if (!ptr)
ptr = std::strstr(currentFile, "NazaraEngine\\");
if (!ptr)
ptr = currentFile;
return ptr;
}
/*!
* \brief Removes the directory
* \return true if remove is successful
*
* \param dirPath Path of the directory
* \param emptyDirectory Remove recursively
*/
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); // If we can't open the directory, we try to delete it
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));
}
/*!
* \brief Sets the current directory
* \return true if directory path exists
*
* \param dirPath Path of the directory
*/
bool Directory::SetCurrent(const String& dirPath)
{
String path = File::AbsolutePath(dirPath);
if (DirectoryImpl::Exists(path))
{
currentPath = path.ToStdString();
return true;
}
else
return false;
}
}

View File

@@ -15,12 +15,6 @@
#error No implementation for this platform
#endif
#if NAZARA_CORE_THREADSAFE && NAZARA_THREADSAFETY_DYNLIB
#include <Nazara/Core/ThreadSafety.hpp>
#else
#include <Nazara/Core/ThreadSafetyOff.hpp>
#endif
#include <Nazara/Core/Debug.hpp>
namespace Nz
@@ -31,35 +25,16 @@ namespace Nz
* \brief Core class that represents a dynamic library loader
*/
/*!
* \brief Constructs a DynLib object by default
*/
DynLib::DynLib() :
m_impl(nullptr)
{
}
/*!
* \brief Destructs the object and calls Unload
*
* \see Unload
*/
DynLib::~DynLib()
{
Unload();
}
DynLib::DynLib() = default;
DynLib::DynLib(DynLib&&) noexcept = default;
DynLib::~DynLib() = default;
/*!
* \brief Gets the last error
* \return Last error
*/
String DynLib::GetLastError() const
std::string DynLib::GetLastError() const
{
NazaraLock(m_mutex)
return m_lastError;
}
@@ -69,11 +44,8 @@ namespace Nz
*
* \remark Produces a NazaraError if library is not loaded with NAZARA_CORE_SAFE defined
*/
DynLibFunc DynLib::GetSymbol(const String& symbol) const
DynLibFunc DynLib::GetSymbol(const char* symbol) const
{
NazaraLock(m_mutex)
#if NAZARA_CORE_SAFE
if (!IsLoaded())
{
@@ -89,7 +61,6 @@ namespace Nz
* \brief Checks whether the library is loaded
* \return true if loaded
*/
bool DynLib::IsLoaded() const
{
return m_impl != nullptr;
@@ -103,38 +74,28 @@ namespace Nz
*
* \remark Produces a NazaraError if library is could not be loaded
*/
bool DynLib::Load(const String& libraryPath)
bool DynLib::Load(const std::filesystem::path& libraryPath)
{
NazaraLock(m_mutex)
Unload();
std::unique_ptr<DynLibImpl> impl(new DynLibImpl(this));
auto impl = std::make_unique<DynLibImpl>(this);
if (!impl->Load(libraryPath, &m_lastError))
{
NazaraError("Failed to load library: " + m_lastError);
return false;
}
m_impl = impl.release();
m_impl = std::move(impl);
return true;
}
/*!
* \brief Unloads the library
*/
void DynLib::Unload()
{
NazaraLock(m_mutex)
if (IsLoaded())
{
m_impl->Unload();
delete m_impl;
m_impl = nullptr;
}
m_impl.reset();
}
DynLib& DynLib::operator=(DynLib&&) noexcept = default;
}

View File

@@ -3,8 +3,9 @@
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/Directory.hpp>
#include <Nazara/Core/CallOnExit.hpp>
#include <Nazara/Core/Log.hpp>
#include <Nazara/Core/StringExt.hpp>
#include <cstdlib>
#include <stdexcept>
@@ -82,25 +83,21 @@ namespace Nz
* \param code Code of the error
*/
String Error::GetLastSystemError(unsigned int code)
std::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);
nullptr,
code,
0,
reinterpret_cast<LPWSTR>(&buffer),
0,
nullptr);
String error(String::Unicode(buffer));
LocalFree(buffer);
error.Trim(); // For an unknown reason, Windows put two-three line return after the message
return error;
CallOnExit freeOnExit([buffer] { LocalFree(buffer); });
return FromWideString(buffer);
#elif defined(NAZARA_PLATFORM_POSIX)
return std::strerror(code);
#else
@@ -166,7 +163,7 @@ namespace Nz
void Error::Trigger(ErrorType type, const String& error, unsigned int line, const char* file, const char* function)
{
file = Nz::Directory::GetCurrentFileRelativeToEngine(file);
file = GetCurrentFileRelativeToEngine(file);
if (type == ErrorType_AssertFailed || (s_flags & ErrorFlag_Silent) == 0 || (s_flags & ErrorFlag_SilentDisabled) != 0)
Log::WriteError(type, error, line, file, function);
@@ -186,6 +183,17 @@ namespace Nz
throw std::runtime_error(error.ToStdString());
}
const char* Error::GetCurrentFileRelativeToEngine(const char* file)
{
if (const char* ptr = std::strstr(file, "NazaraEngine/"))
return ptr;
if (const char* ptr = std::strstr(file, "NazaraEngine\\"))
return ptr;
return file;
}
UInt32 Error::s_flags = ErrorFlag_None;
String Error::s_lastError;
const char* Error::s_lastErrorFunction = "";

View File

@@ -5,7 +5,6 @@
#include <Nazara/Core/File.hpp>
#include <Nazara/Core/AbstractHash.hpp>
#include <Nazara/Core/Config.hpp>
#include <Nazara/Core/Directory.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/ErrorFlags.hpp>
#include <Nazara/Core/StringStream.hpp>
@@ -19,12 +18,6 @@
#error OS not handled
#endif
#if NAZARA_CORE_THREADSAFE && NAZARA_THREADSAFETY_FILE
#include <Nazara/Core/ThreadSafety.hpp>
#else
#include <Nazara/Core/ThreadSafetyOff.hpp>
#endif
#include <Nazara/Core/Debug.hpp>
namespace Nz
@@ -39,10 +32,7 @@ namespace Nz
* \brief Constructs a File object by default
*/
File::File() :
m_impl(nullptr)
{
}
File::File() = default;
/*!
* \brief Constructs a File object with a file path
@@ -50,7 +40,7 @@ namespace Nz
* \param filePath Path to the file
*/
File::File(const String& filePath) :
File::File(const std::filesystem::path& filePath) :
File()
{
SetFile(filePath);
@@ -63,7 +53,7 @@ namespace Nz
* \param openMode Flag of the file
*/
File::File(const String& filePath, OpenModeFlags openMode) :
File::File(const std::filesystem::path& filePath, OpenModeFlags openMode) :
File()
{
Open(filePath, openMode);
@@ -75,6 +65,8 @@ namespace Nz
* \see Close
*/
File::File(File&& file) noexcept = default;
File::~File()
{
Close();
@@ -82,14 +74,12 @@ namespace Nz
/*!
* \brief Copies this file to a new file path
* \return true if copy is successful
*
* \param newFilePath Path of the new file
*/
bool File::Copy(const String& newFilePath)
void File::Copy(const std::filesystem::path& newFilePath)
{
return Copy(m_filePath, newFilePath);
std::filesystem::copy(m_filePath, newFilePath);
}
/*!
@@ -98,13 +88,9 @@ namespace Nz
void File::Close()
{
NazaraLock(m_mutex)
if (m_impl)
{
m_impl->Close();
delete m_impl;
m_impl = nullptr;
m_impl.reset();
m_openMode = OpenMode_NotOpen;
}
@@ -117,11 +103,9 @@ namespace Nz
bool File::Delete()
{
NazaraLock(m_mutex)
Close();
return Delete(m_filePath);
return std::filesystem::remove(m_filePath);
}
/*!
@@ -133,8 +117,6 @@ namespace Nz
bool File::EndOfFile() const
{
NazaraLock(m_mutex)
#if NAZARA_CORE_SAFE
if (!IsOpen())
{
@@ -167,24 +149,10 @@ namespace Nz
bool File::Exists() const
{
NazaraLock(m_mutex)
if (IsOpen())
return true; // Le fichier est ouvert, donc il existe
else
return Exists(m_filePath);
}
/*!
* \brief Gets the creation time of the file
* \return Information about the creation time
*/
time_t File::GetCreationTime() const
{
NazaraLock(m_mutex)
return GetCreationTime(m_filePath);
return std::filesystem::exists(m_filePath);
}
/*!
@@ -196,8 +164,6 @@ namespace Nz
UInt64 File::GetCursorPos() const
{
NazaraLock(m_mutex)
NazaraAssert(IsOpen(), "File is not open");
return m_impl->GetCursorPos();
@@ -207,72 +173,32 @@ namespace Nz
* \brief Gets the directory of the file
* \return Directory of the file
*/
String File::GetDirectory() const
std::filesystem::path File::GetDirectory() const
{
NazaraLock(m_mutex)
return m_filePath.SubStringTo(NAZARA_DIRECTORY_SEPARATOR, -1, true, true);
return m_filePath.parent_path();
}
/*!
* \brief Gets the name of the file
* \return Name of the file
*/
String File::GetFileName() const
std::filesystem::path File::GetFileName() const
{
NazaraLock(m_mutex)
return m_filePath.SubStringFrom(NAZARA_DIRECTORY_SEPARATOR, -1, true);
}
/*!
* \brief Gets the last time the file was accessed
* \return Information about the last access time
*/
time_t File::GetLastAccessTime() const
{
NazaraLock(m_mutex)
return GetLastAccessTime(m_filePath);
}
/*!
* \brief Gets the last time the file was written
* \return Information about the last writing time
*/
time_t File::GetLastWriteTime() const
{
NazaraLock(m_mutex)
return GetLastWriteTime(m_filePath);
return m_filePath.filename();
}
/*!
* \brief Gets the path of the file
* \return Path of the file
*/
String File::GetPath() const
std::filesystem::path File::GetPath() const
{
NazaraLock(m_mutex)
return m_filePath;
}
/*!
* \brief Gets the size of the file
* \return Size of the file
*/
UInt64 File::GetSize() const
{
NazaraLock(m_mutex)
return GetSize(m_filePath);
return std::filesystem::file_size(m_filePath);
}
/*!
@@ -282,8 +208,6 @@ namespace Nz
bool File::IsOpen() const
{
NazaraLock(m_mutex)
return m_impl != nullptr;
}
@@ -298,26 +222,24 @@ namespace Nz
bool File::Open(OpenModeFlags openMode)
{
NazaraLock(m_mutex)
Close();
if (m_filePath.IsEmpty())
if (m_filePath.empty())
return false;
if (openMode == OpenMode_NotOpen)
return false;
std::unique_ptr<FileImpl> impl(new FileImpl(this));
std::unique_ptr<FileImpl> impl = std::make_unique<FileImpl>(this);
if (!impl->Open(m_filePath, openMode))
{
ErrorFlags flags(ErrorFlag_Silent); // Silent by default
NazaraError("Failed to open \"" + m_filePath + "\": " + Error::GetLastSystemError());
NazaraError("Failed to open \"" + m_filePath.generic_u8string() + "\": " + Error::GetLastSystemError());
return false;
}
m_openMode = openMode;
m_impl = impl.release();
m_impl = std::move(impl);
if (m_openMode & OpenMode_Text)
m_streamOptions |= StreamOption_Text;
@@ -337,38 +259,14 @@ namespace Nz
* \remark Produces a NazaraError if OS error to open a file
*/
bool File::Open(const String& filePath, OpenModeFlags openMode)
bool File::Open(const std::filesystem::path& filePath, OpenModeFlags openMode)
{
NazaraLock(m_mutex)
Close();
SetFile(filePath);
return Open(openMode);
}
/*!
* \brief Renames the file with a new name
* \return true if rename is successful
*/
bool File::Rename(const String& newFilePath)
{
NazaraLock(m_mutex)
bool open = IsOpen();
Close();
bool success = Rename(m_filePath, newFilePath);
if (success)
m_filePath = NormalizePath(newFilePath);
if (open)
Open();
return success;
}
/*!
* \brief Sets the position of the cursor
* \return true if cursor is successfully positioned
@@ -381,8 +279,6 @@ namespace Nz
bool File::SetCursorPos(CursorPosition pos, Int64 offset)
{
NazaraLock(m_mutex)
NazaraAssert(IsOpen(), "File is not open");
return m_impl->SetCursorPos(pos, offset);
@@ -399,8 +295,6 @@ namespace Nz
bool File::SetCursorPos(UInt64 offset)
{
NazaraLock(m_mutex)
NazaraAssert(IsOpen(), "File is not open");
return m_impl->SetCursorPos(CursorPosition_AtBegin, offset);
@@ -413,29 +307,24 @@ namespace Nz
* \remark Produces a NazaraError if file path can not be open
*/
bool File::SetFile(const String& filePath)
bool File::SetFile(const std::filesystem::path& filePath)
{
NazaraLock(m_mutex)
if (IsOpen())
{
if (filePath.IsEmpty())
if (filePath.empty())
return false;
std::unique_ptr<FileImpl> impl(new FileImpl(this));
std::unique_ptr<FileImpl> impl = std::make_unique<FileImpl>(this);
if (!impl->Open(filePath, m_openMode))
{
NazaraError("Failed to open new file; " + Error::GetLastSystemError());
return false;
}
m_impl->Close();
delete m_impl;
m_impl = impl.release();
m_impl = std::move(impl);
}
m_filePath = AbsolutePath(filePath);
m_filePath = std::filesystem::absolute(filePath);
return true;
}
@@ -450,317 +339,13 @@ namespace Nz
*/
bool File::SetSize(UInt64 size)
{
NazaraLock(m_mutex)
NazaraAssert(IsOpen(), "File is not open");
NazaraAssert(IsWritable(), "File is not writable");
return m_impl->SetSize(size);
}
/*!
* \brief Sets the file path
* \return A reference to this
*
* \remark Produces a NazaraError if file path can not be open
*/
File& File::operator=(const String& filePath)
{
SetFile(filePath);
return *this;
}
/*!
* \brief Gets the absolute path of the file
* \return Absolute path of the file
*
* \param filePath Path of the file
*
* \remark Produces a NazaraError if filePath is weird with NAZARA_PLATFORM_WINDOWS defined
*/
String File::AbsolutePath(const String& filePath)
{
// We don't use OS functions because they only work for existing path
String path = NormalizePath(filePath);
if (path.IsEmpty())
return String();
String base;
unsigned int start;
#ifdef NAZARA_PLATFORM_WINDOWS
if (path.Match("?:*"))
start = 1;
else if (path.Match("\\\\*"))
{
base = "\\\\";
start = 2;
}
else if (path.StartsWith('\\')) // Special : '\' refering to root
{
String drive = Directory::GetCurrent().SubStringTo('\\');
String end = path.SubString(1, -1);
if (end.IsEmpty())
path = drive;
else
path = drive + '\\' + end;
start = 1;
}
else
{
NazaraError("Path unrecognized");
return path;
}
#elif defined(NAZARA_PLATFORM_POSIX)
base = '/';
start = 0;
#else
#error OS case not implemented
#endif
static String upDir = NAZARA_DIRECTORY_SEPARATOR + String('.');
if (path.Find(upDir) == String::npos)
return path;
std::vector<String> sep;
if (path.Split(sep, NAZARA_DIRECTORY_SEPARATOR) <= 1)
return path;
// We have the absolute path, but we need to clean it up
for (unsigned int i = 0; i < sep.size(); ++i)
{
if (sep[i] == '.')
sep.erase(sep.begin() + i--);
else if (sep[i] == "..")
{
if (i > start) // If we are not in the protected area
sep.erase(sep.begin() + i--);
sep.erase(sep.begin() + i--);
}
}
StringStream stream(base);
for (unsigned int i = 0; i < sep.size(); ++i)
{
if (i != sep.size()-1)
stream << sep[i] << NAZARA_DIRECTORY_SEPARATOR;
else
stream << sep[i];
}
return stream;
}
/*!
* \brief Copies the first file to a new file path
* \return true if copy is successful
*
* \param sourcePath Path of the original file
* \param targetPath Path of the copied file
*/
bool File::Copy(const String& sourcePath, const String& targetPath)
{
if (sourcePath.IsEmpty() || targetPath.IsEmpty())
return false;
return FileImpl::Copy(NormalizePath(sourcePath), NormalizePath(targetPath));
}
/*!
* \brief Deletes the file
* \return true if delete is successful
*
* \param filePath Path of the file
*/
bool File::Delete(const String& filePath)
{
if (filePath.IsEmpty())
return false;
return FileImpl::Delete(NormalizePath(filePath));
}
/*!
* \brief Checks whether the file exists
* \return true if file exists
*
* \param filePath Path of the file
*/
bool File::Exists(const String& filePath)
{
if (filePath.IsEmpty())
return false;
return FileImpl::Exists(NormalizePath(filePath));
}
/*!
* \brief Gets the creation time of the file
* \return Information about the creation time
*
* \param filePath Path of the file
*/
time_t File::GetCreationTime(const String& filePath)
{
if (filePath.IsEmpty())
return 0;
return FileImpl::GetCreationTime(NormalizePath(filePath));
}
/*!
* \brief Gets the directory of the file
* \return Directory of the file
*
* \param filePath Path of the file
*/
String File::GetDirectory(const String& filePath)
{
return filePath.SubStringTo(NAZARA_DIRECTORY_SEPARATOR, -1, true, true);
}
/*!
* \brief Gets the last time the file was accessed
* \return Information about the last access time
*
* \param filePath Path of the file
*/
time_t File::GetLastAccessTime(const String& filePath)
{
if (filePath.IsEmpty())
return 0;
return FileImpl::GetLastAccessTime(NormalizePath(filePath));
}
/*!
* \brief Gets the last time the file was written
* \return Information about the last writing time
*
* \param filePath Path of the file
*/
time_t File::GetLastWriteTime(const String& filePath)
{
if (filePath.IsEmpty())
return 0;
return FileImpl::GetLastWriteTime(NormalizePath(filePath));
}
/*!
* \brief Gets the size of the file
* \return Size of the file
*
* \param filePath Path of the file
*/
UInt64 File::GetSize(const String& filePath)
{
if (filePath.IsEmpty())
return 0;
return FileImpl::GetSize(NormalizePath(filePath));
}
/*!
* \brief Checks whether the file path is absolute
* \return true if path is absolute
*
* \param filePath Path to test
*/
bool File::IsAbsolute(const String& filePath)
{
String path(filePath.Trimmed());
if (path.IsEmpty())
return false;
path = NormalizeSeparators(path);
#ifdef NAZARA_PLATFORM_WINDOWS
if (path.Match("?:*")) // Ex: C:\Hello
return true;
else if (path.Match("\\\\*")) // Ex: \\Laptop
return true;
else if (path.StartsWith('\\')) // Special : '\' referring to the root
return true;
else
return false;
#elif defined(NAZARA_PLATFORM_POSIX)
return path.StartsWith('/');
#else
#error OS case not implemented
#endif
}
/*!
* \brief Normalizes the file path
* \return Path normalized (replacing '/' with '\\' on Windows, ...)
*
* \param filePath Path to normalize
*/
String File::NormalizePath(const String& filePath)
{
String path = NormalizeSeparators(filePath.Trimmed());
if (!IsAbsolute(path))
path = Directory::GetCurrent() + NAZARA_DIRECTORY_SEPARATOR + path;
while (path.EndsWith(NAZARA_DIRECTORY_SEPARATOR))
path.Resize(-1);
return path;
}
/*!
* \brief Normalizes the path separator
* \return Path normalized (replacing '/' with '\\' on Windows, ...)
*
* \param filePath Path to normalize
*/
String File::NormalizeSeparators(const String& filePath)
{
String path(filePath);
#if defined(NAZARA_PLATFORM_WINDOWS)
path.Replace('/', '\\');
#elif defined(NAZARA_PLATFORM_LINUX)
path.Replace('\\', '/');
#else
#error OS case not implemented
#endif
return path;
}
/*!
* \brief Renames the file with a new name
* \return true if rename is successful
*
* \param sourcePath Path of the original file
* \param targetPath Path of the renamed file
*/
bool File::Rename(const String& sourcePath, const String& targetPath)
{
if (sourcePath.IsEmpty() || targetPath.IsEmpty())
return false;
return FileImpl::Rename(NormalizePath(sourcePath), NormalizePath(targetPath));
}
File& File::operator=(File&& file) noexcept = default;
/*!
* \brief Flushes the stream
@@ -770,8 +355,6 @@ namespace Nz
void File::FlushStream()
{
NazaraLock(m_mutex)
NazaraAssert(IsOpen(), "File is not open");
m_impl->Flush();
@@ -789,8 +372,6 @@ namespace Nz
std::size_t File::ReadBlock(void* buffer, std::size_t size)
{
NazaraLock(m_mutex)
NazaraAssert(IsOpen(), "File is not open");
if (size == 0)
@@ -822,8 +403,6 @@ namespace Nz
std::size_t File::WriteBlock(const void* buffer, std::size_t size)
{
NazaraLock(m_mutex)
NazaraAssert(IsOpen(), "File is not open");
if (size == 0)

View File

@@ -8,6 +8,8 @@
#include <Nazara/Core/StringStream.hpp>
#include <array>
#include <ctime>
#include <filesystem>
#include <sstream>
#include <Nazara/Core/Debug.hpp>
namespace Nz
@@ -25,7 +27,7 @@ namespace Nz
*/
FileLogger::FileLogger(const String& logPath) :
m_outputFile(logPath),
m_outputPath(logPath.ToStdString()),
m_forceStdOutput(false),
m_stdReplicationEnabled(true),
m_timeLoggingEnabled(true)
@@ -107,9 +109,10 @@ namespace Nz
m_forceStdOutput = false;
});
if (!m_outputFile.IsOpen())
if (!m_outputFile.is_open())
{
if (!m_outputFile.Open(OpenMode_Text | OpenMode_Truncate | OpenMode_WriteOnly))
m_outputFile.open(m_outputPath, std::ios_base::trunc | std::ios_base::out);
if (!m_outputFile.is_open())
{
NazaraError("Failed to open output file");
return;
@@ -117,7 +120,7 @@ namespace Nz
}
// Apply some processing before writing
StringStream stream;
std::ostringstream stream;
if (m_timeLoggingEnabled)
{
std::array<char, 24> buffer;
@@ -130,7 +133,7 @@ namespace Nz
stream << string << '\n';
m_outputFile.Write(stream);
m_outputFile << stream.str();
}
/*!
@@ -148,6 +151,6 @@ namespace Nz
void FileLogger::WriteError(ErrorType type, const String& error, unsigned int line, const char* file, const char* function)
{
AbstractLogger::WriteError(type, error, line, file, function);
m_outputFile.Flush();
m_outputFile.flush();
}
}

View File

@@ -1,80 +0,0 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Mutex.hpp>
#include <Nazara/Core/Error.hpp>
#if defined(NAZARA_PLATFORM_WINDOWS)
#include <Nazara/Core/Win32/MutexImpl.hpp>
#elif defined(NAZARA_PLATFORM_POSIX)
#include <Nazara/Core/Posix/MutexImpl.hpp>
#else
#error Lack of implementation: Mutex
#endif
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
/*!
* \ingroup core
* \class Nz::Mutex
* \brief Core class that represents a binary semaphore, a mutex
*
* \remark The mutex is recursive, it means that a thread who owns the mutex can call the same function which needs the same mutex
*/
/*!
* \brief Constructs a Mutex object by default
*/
Mutex::Mutex()
{
m_impl = new MutexImpl;
}
/*!
* \brief Destructs the object
*/
Mutex::~Mutex()
{
delete m_impl;
}
/*!
* \brief Locks the mutex
*
* If another thread has already locked the mutex, a call to lock will block execution until the lock is acquired. A thread may call lock on a recursive mutex repeatedly. Ownership will only be released after the thread makes a matching number of calls to unlock
*/
void Mutex::Lock()
{
NazaraAssert(m_impl, "Cannot lock a moved mutex");
m_impl->Lock();
}
/*!
* \brief Tries to lock the mutex
* \return true if the lock was acquired successfully
*/
bool Mutex::TryLock()
{
NazaraAssert(m_impl, "Cannot lock a moved mutex");
return m_impl->TryLock();
}
/*!
* \brief Unlocks the mutex
*
* Unlocks the mutex if its level of ownership is 1 (there was exactly one more call to Lock() than there were calls to Unlock() made by this thread), reduces the level of ownership by 1 otherwise
*/
void Mutex::Unlock()
{
NazaraAssert(m_impl, "Cannot unlock a moved mutex");
m_impl->Unlock();
}
}

View File

@@ -3,10 +3,8 @@
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/PluginManager.hpp>
#include <Nazara/Core/Directory.hpp>
#include <Nazara/Core/DynLib.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/File.hpp>
#include <memory>
#include <Nazara/Core/Debug.hpp>
@@ -17,7 +15,7 @@ namespace Nz
using PluginLoad = int (*)();
using PluginUnload = void (*)();
String s_pluginFiles[] =
std::filesystem::path s_pluginFiles[] =
{
"PluginAssimp", // Plugin_Assimp
};
@@ -37,7 +35,7 @@ namespace Nz
* \remark Produces a NazaraError if not initialized
*/
void PluginManager::AddDirectory(const String& directoryPath)
void PluginManager::AddDirectory(const std::filesystem::path& directoryPath)
{
if (!Initialize())
{
@@ -45,7 +43,7 @@ namespace Nz
return;
}
s_directories.insert(File::AbsolutePath(directoryPath));
s_directories.insert(std::filesystem::absolute(directoryPath));
}
/*!
@@ -79,9 +77,13 @@ namespace Nz
bool PluginManager::Mount(Plugin plugin)
{
Nz::String pluginName = s_pluginFiles[plugin];
std::filesystem::path pluginName = s_pluginFiles[plugin];
#ifdef NAZARA_DEBUG
if (Mount(pluginName + "-d", true))
std::filesystem::path debugPath = pluginName;
debugPath += "-d";
if (Mount(debugPath, true))
return true;
#endif
@@ -102,7 +104,7 @@ namespace Nz
* \remark Produces a NazaraError if fail to initialize the plugin with PluginLoad
*/
bool PluginManager::Mount(const String& pluginPath, bool appendExtension)
bool PluginManager::Mount(const std::filesystem::path& pluginPath, bool appendExtension)
{
if (!Initialize())
{
@@ -110,23 +112,17 @@ namespace Nz
return false;
}
String path = pluginPath;
if (appendExtension && !path.EndsWith(NAZARA_DYNLIB_EXTENSION))
std::filesystem::path path = pluginPath;
if (appendExtension && path.extension() == NAZARA_DYNLIB_EXTENSION)
path += NAZARA_DYNLIB_EXTENSION;
bool exists = false;
if (!File::IsAbsolute(path))
if (!path.is_absolute())
{
for (const String& dir : s_directories)
for (const std::filesystem::path& dir : s_directories)
{
String testPath;
testPath.Reserve(dir.GetSize() + path.GetSize() + 10);
testPath = dir;
testPath += NAZARA_DIRECTORY_SEPARATOR;
testPath += path;
if (File::Exists(testPath))
std::filesystem::path testPath = dir / path;
if (std::filesystem::exists(testPath))
{
path = testPath;
exists = true;
@@ -134,7 +130,7 @@ namespace Nz
}
}
}
else if (File::Exists(path))
else if (std::filesystem::exists(path))
exists = true;
if (!exists)
@@ -143,7 +139,7 @@ namespace Nz
return false;
}
std::unique_ptr<DynLib> library(new DynLib);
std::unique_ptr<DynLib> library = std::make_unique<DynLib>();
if (!library->Load(path))
{
NazaraError("Failed to load plugin");
@@ -163,7 +159,8 @@ namespace Nz
return false;
}
s_plugins[pluginPath] = library.release();
std::filesystem::path canonicalPath = std::filesystem::canonical(pluginPath);
s_plugins[canonicalPath] = std::move(library);
return true;
}
@@ -176,7 +173,7 @@ namespace Nz
* \remark Produces a NazaraError if not initialized
*/
void PluginManager::RemoveDirectory(const String& directoryPath)
void PluginManager::RemoveDirectory(const std::filesystem::path& directoryPath)
{
if (!Initialize())
{
@@ -184,7 +181,7 @@ namespace Nz
return;
}
s_directories.erase(File::AbsolutePath(directoryPath));
s_directories.erase(std::filesystem::canonical(directoryPath));
}
/*!
@@ -210,7 +207,7 @@ namespace Nz
* \remark Produces a NazaraError if plugin is not loaded
*/
void PluginManager::Unmount(const String& pluginPath)
void PluginManager::Unmount(const std::filesystem::path& pluginPath)
{
if (!Initialize())
{
@@ -218,7 +215,8 @@ namespace Nz
return;
}
auto it = s_plugins.find(pluginPath);
std::filesystem::path canonicalPath = std::filesystem::canonical(pluginPath);
auto it = s_plugins.find(canonicalPath);
if (it == s_plugins.end())
{
NazaraError("Plugin not loaded");
@@ -229,9 +227,6 @@ namespace Nz
if (func)
func();
it->second->Unload();
delete it->second;
s_plugins.erase(it);
}
@@ -253,15 +248,12 @@ namespace Nz
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;
std::set<std::filesystem::path> PluginManager::s_directories;
std::unordered_map<std::filesystem::path, std::unique_ptr<DynLib>, PluginManager::PathHash> PluginManager::s_plugins;
bool PluginManager::s_initialized = false;
}

View File

@@ -1,52 +0,0 @@
// Copyright (C) 2015 Alexandre Janniaux
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Posix/ConditionVariableImpl.hpp>
#include <Nazara/Core/Posix/MutexImpl.hpp>
#include <sys/time.h>
#include <time.h>
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
ConditionVariableImpl::ConditionVariableImpl()
{
pthread_cond_init(&m_cv, nullptr);
}
ConditionVariableImpl::~ConditionVariableImpl()
{
pthread_cond_destroy(&m_cv);
}
void ConditionVariableImpl::Signal()
{
pthread_cond_signal(&m_cv);
}
void ConditionVariableImpl::SignalAll()
{
pthread_cond_broadcast(&m_cv);
}
void ConditionVariableImpl::Wait(MutexImpl* mutex)
{
pthread_cond_wait(&m_cv, &mutex->m_handle);
}
bool ConditionVariableImpl::Wait(MutexImpl* mutex, UInt32 timeout)
{
// get the current time
timeval tv;
gettimeofday(&tv, nullptr);
// construct the time limit (current time + time to wait)
timespec ti;
ti.tv_nsec = (tv.tv_usec + (timeout % 1000)) * 1000000;
ti.tv_sec = tv.tv_sec + (timeout / 1000) + (ti.tv_nsec / 1000000000);
ti.tv_nsec %= 1000000000;
return pthread_cond_timedwait(&m_cv,&mutex->m_handle, &ti) != 0;
}
}

View File

@@ -1,36 +0,0 @@
// Copyright (C) 2015 Alexandre Janniaux
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
// http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
#pragma once
#ifndef NAZARA_CONDITIONVARIABLEIMPL_HPP
#define NAZARA_CONDITIONVARIABLEIMPL_HPP
#include <Nazara/Prerequisites.hpp>
#include <pthread.h>
namespace Nz
{
class MutexImpl;
class ConditionVariableImpl
{
public:
ConditionVariableImpl();
~ConditionVariableImpl();
void Signal();
void SignalAll();
void Wait(MutexImpl* mutex);
bool Wait(MutexImpl* mutex, UInt32 timeout);
private:
pthread_cond_t m_cv;
};
}
#endif // NAZARA_CONDITIONVARIABLEIMPL_HPP

View File

@@ -1,120 +0,0 @@
// Copyright (C) 2015 Alexandre Janniaux
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Posix/DirectoryImpl.hpp>
#include <Nazara/Core/Directory.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/StackArray.hpp>
#include <Nazara/Core/String.hpp>
#include <cstring>
#include <errno.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <unistd.h>
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
DirectoryImpl::DirectoryImpl(const Directory* parent) :
m_parent(parent)
{
}
void DirectoryImpl::Close()
{
closedir(m_handle);
}
String DirectoryImpl::GetResultName() const
{
return m_result->d_name;
}
UInt64 DirectoryImpl::GetResultSize() const
{
String path = m_parent->GetPath();
std::size_t pathSize = path.GetSize();
std::size_t resultNameSize = std::strlen(m_result->d_name);
std::size_t fullNameSize = pathSize + 1 + resultNameSize;
StackArray<char> fullName = NazaraStackArrayNoInit(char, fullNameSize + 1);
std::memcpy(&fullName[0], path.GetConstBuffer(), pathSize * sizeof(char));
fullName[pathSize] = '/';
std::memcpy(&fullName[pathSize + 1], m_result->d_name, resultNameSize * sizeof(char));
fullName[fullNameSize] = '\0';
struct stat64 results;
stat64(fullName.data(), &results);
return results.st_size;
}
bool DirectoryImpl::IsResultDirectory() const
{
//TODO: Fix d_type handling (field can be missing or be a symbolic link, both cases which must be handled by calling stat)
return m_result->d_type == DT_DIR;
}
bool DirectoryImpl::NextResult()
{
if ((m_result = readdir64(m_handle)))
return true;
else
{
if (errno == EBADF || errno == EOVERFLOW)
NazaraError("Unable to get next result: " + Error::GetLastSystemError());
return false;
}
}
bool DirectoryImpl::Open(const String& dirPath)
{
m_handle = opendir(dirPath.GetConstBuffer());
if (!m_handle)
{
NazaraError("Unable to open directory: " + Error::GetLastSystemError());
return false;
}
return true;
}
bool DirectoryImpl::Create(const String& dirPath)
{
mode_t permissions = S_IRWXU | S_IRWXG | S_IRWXO; // 777
return mkdir(dirPath.GetConstBuffer(), permissions) != -1;
}
bool DirectoryImpl::Exists(const String& dirPath)
{
struct stat64 filestats;
if (stat64(dirPath.GetConstBuffer(), &filestats) == -1) // error
return false;
return S_ISDIR(filestats.st_mode) || S_ISREG(filestats.st_mode);
}
String DirectoryImpl::GetCurrent()
{
String currentPath;
char path[MAXPATHLEN];
if (getcwd(path, MAXPATHLEN))
currentPath = path;
else
NazaraError("Unable to get current directory: " + Error::GetLastSystemError()); // Bug: initialisation -> if no path for log !
return currentPath;
}
bool DirectoryImpl::Remove(const String& dirPath)
{
bool success = rmdir(dirPath.GetConstBuffer()) != -1;
return success;
}
}

View File

@@ -1,52 +0,0 @@
// Copyright (C) 2015 Alexandre Janniaux
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_DIRECTORYIMPL_HPP
#define NAZARA_DIRECTORYIMPL_HPP
#include <Nazara/Prerequisites.hpp>
#include <dirent.h>
namespace Nz
{
class Directory;
class String;
class DirectoryImpl
{
public:
DirectoryImpl(const Directory* parent);
DirectoryImpl(const DirectoryImpl&) = delete;
DirectoryImpl(DirectoryImpl&&) = delete; ///TODO
~DirectoryImpl() = default;
void Close();
String GetResultName() const;
UInt64 GetResultSize() const;
bool IsResultDirectory() const;
bool NextResult();
bool Open(const String& dirPath);
DirectoryImpl& operator=(const DirectoryImpl&) = delete;
DirectoryImpl& operator=(DirectoryImpl&&) = delete; ///TODO
static bool Create(const String& dirPath);
static bool Exists(const String& dirPath);
static String GetCurrent();
static bool Remove(const String& dirPath);
private:
const Directory* m_parent;
DIR* m_handle;
dirent64* m_result;
};
}
#endif // NAZARA_DIRECTORYIMPL_HPP

View File

@@ -13,13 +13,14 @@
namespace Nz
{
FileImpl::FileImpl(const File* parent) :
m_fileDescriptor(-1),
m_endOfFile(false),
m_endOfFileUpdated(true)
{
NazaraUnused(parent);
}
void FileImpl::Close()
FileImpl::~FileImpl()
{
if (m_fileDescriptor != -1)
close(m_fileDescriptor);
@@ -52,7 +53,7 @@ namespace Nz
return static_cast<UInt64>(position);
}
bool FileImpl::Open(const String& filePath, OpenModeFlags mode)
bool FileImpl::Open(const std::filesystem::path& filePath, OpenModeFlags mode)
{
int flags;
mode_t permissions = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
@@ -75,10 +76,10 @@ namespace Nz
if (mode & OpenMode_Truncate)
flags |= O_TRUNC;
m_fileDescriptor = open64(filePath.GetConstBuffer(), flags, permissions);
m_fileDescriptor = open64(filePath.generic_u8string().data(), flags, permissions);
if (m_fileDescriptor == -1)
{
NazaraError("Failed to open \"" + filePath + "\" : " + Error::GetLastSystemError());
NazaraError("Failed to open \"" + filePath.generic_u8string() + "\" : " + Error::GetLastSystemError());
return false;
}
@@ -177,121 +178,4 @@ namespace Nz
return written;
}
bool FileImpl::Copy(const String& sourcePath, const String& targetPath)
{
int fd1 = open64(sourcePath.GetConstBuffer(), O_RDONLY);
if (fd1 == -1)
{
NazaraError("Fail to open input file (" + sourcePath + "): " + Error::GetLastSystemError());
return false;
}
mode_t permissions;
struct stat sb;
if (fstat(fd1, &sb) == -1) // get permission from first file
{
NazaraWarning("Could not get permissions of source file");
permissions = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
}
else
{
permissions = sb.st_mode & ~S_IFMT; // S_IFMT: bit mask for the file type bit field -> ~S_IFMT: general permissions
}
int fd2 = open64(targetPath.GetConstBuffer(), O_WRONLY | O_TRUNC, permissions);
if (fd2 == -1)
{
NazaraError("Fail to open output file (" + targetPath + "): " + Error::GetLastSystemError()); // TODO: more info ?
close(fd1);
return false;
}
char buffer[512];
ssize_t bytes;
do
{
bytes = read(fd1,buffer,512);
if (bytes == -1)
{
close(fd1);
close(fd2);
NazaraError("An error occured from copy : " + Error::GetLastSystemError());
return false;
}
write(fd2,buffer,bytes);
}
while (bytes == 512);
close(fd1);
close(fd2);
return true;
}
bool FileImpl::Delete(const String& filePath)
{
bool success = unlink(filePath.GetConstBuffer()) != -1;
if (success)
return true;
else
{
NazaraError("Failed to delete file (" + filePath + "): " + Error::GetLastSystemError());
return false;
}
}
bool FileImpl::Exists(const String& filePath)
{
const char* path = filePath.GetConstBuffer();
if (access(path, F_OK) != -1)
return true;
return false;
}
time_t FileImpl::GetCreationTime(const String& filePath)
{
NazaraUnused(filePath);
NazaraWarning("Posix has no creation time information");
return 0;
}
time_t FileImpl::GetLastAccessTime(const String& filePath)
{
struct stat64 stats;
stat64(filePath.GetConstBuffer(), &stats);
return stats.st_atime;
}
time_t FileImpl::GetLastWriteTime(const String& filePath)
{
struct stat64 stats;
stat64(filePath.GetConstBuffer(), &stats);
return stats.st_mtime;
}
UInt64 FileImpl::GetSize(const String& filePath)
{
struct stat64 stats;
stat64(filePath.GetConstBuffer(), &stats);
return static_cast<UInt64>(stats.st_size);
}
bool FileImpl::Rename(const String& sourcePath, const String& targetPath)
{
bool success = std::rename(sourcePath.GetConstBuffer(), targetPath.GetConstBuffer()) != -1;
if (success)
return true;
else
{
NazaraError("Unable to rename file: " + Error::GetLastSystemError());
return false;
}
}
}

View File

@@ -14,6 +14,7 @@
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Core/Enums.hpp>
#include <ctime>
#include <filesystem>
namespace Nz
{
@@ -28,11 +29,10 @@ namespace Nz
FileImpl(FileImpl&&) = delete; ///TODO
~FileImpl() = default;
void Close();
bool EndOfFile() const;
void Flush();
UInt64 GetCursorPos() const;
bool Open(const String& filePath, OpenModeFlags mode);
bool Open(const std::filesystem::path& filePath, OpenModeFlags mode);
std::size_t Read(void* buffer, std::size_t size);
bool SetCursorPos(CursorPosition pos, Int64 offset);
bool SetSize(UInt64 size);
@@ -41,15 +41,6 @@ namespace Nz
FileImpl& operator=(const FileImpl&) = delete;
FileImpl& operator=(FileImpl&&) = delete; ///TODO
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:
int m_fileDescriptor;
mutable bool m_endOfFile;

View File

@@ -1,38 +0,0 @@
// Copyright (C) 2015 Alexandre Janniaux
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Posix/MutexImpl.hpp>
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
MutexImpl::MutexImpl()
{
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&m_handle, &attr);
}
MutexImpl::~MutexImpl()
{
pthread_mutex_destroy(&m_handle);
}
void MutexImpl::Lock()
{
pthread_mutex_lock(&m_handle);
}
bool MutexImpl::TryLock()
{
return pthread_mutex_trylock(&m_handle) == 0;
}
void MutexImpl::Unlock()
{
pthread_mutex_unlock(&m_handle);
}
}

View File

@@ -1,31 +0,0 @@
// Copyright (C) 2015 Alexandre Janniaux
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_MUTEXIMPL_HPP
#define NAZARA_MUTEXIMPL_HPP
#include <pthread.h>
namespace Nz
{
class MutexImpl
{
friend class ConditionVariableImpl;
public:
MutexImpl();
~MutexImpl();
void Lock();
bool TryLock();
void Unlock();
private:
pthread_mutex_t m_handle;
};
}
#endif // NAZARA_MUTEXIMPL_HPP

View File

@@ -1,73 +0,0 @@
// Copyright (C) 2015 Alexandre Janniaux
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Posix/SemaphoreImpl.hpp>
#include <Nazara/Core/Error.hpp>
#include <time.h>
#include <sys/time.h>
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
SemaphoreImpl::SemaphoreImpl(unsigned int count)
{
if (sem_init(&m_semaphore, 0, count) != 0)
NazaraError("Failed to create semaphore: " + Error::GetLastSystemError());
}
SemaphoreImpl::~SemaphoreImpl()
{
sem_destroy(&m_semaphore);
}
unsigned int SemaphoreImpl::GetCount() const
{
int count=0;
sem_getvalue(const_cast<sem_t*>(&m_semaphore), &count);
return static_cast<unsigned int>(count);
}
void SemaphoreImpl::Post()
{
#if NAZARA_CORE_SAFE
if (sem_post(&m_semaphore)==-1)
NazaraError("Failed to release semaphore: " + Error::GetLastSystemError());
#else
sem_post(&m_semaphore);
#endif
}
void SemaphoreImpl::Wait()
{
#if NAZARA_CORE_SAFE
if (sem_wait(&m_semaphore) == -1 )
NazaraError("Failed to wait for semaphore: " + Error::GetLastSystemError());
#else
sem_wait(&m_semaphore);
#endif
}
bool SemaphoreImpl::Wait(UInt32 timeout)
{
timeval tv;
gettimeofday(&tv, nullptr);
timespec ti;
ti.tv_nsec = (tv.tv_usec + (timeout % 1000)) * 1000000;
ti.tv_sec = tv.tv_sec + (timeout / 1000) + (ti.tv_nsec / 1000000000);
ti.tv_nsec %= 1000000000;
#if NAZARA_CORE_SAFE
if (sem_timedwait(&m_semaphore, &ti) != 0)
{
NazaraError("Failed to wait for semaphore: " + Error::GetLastSystemError());
return false;
}
return true;
#else
return sem_timedwait(&m_semaphore, &ti) != 0;
#endif
}
}

View File

@@ -1,31 +0,0 @@
// Copyright (C) 2015 Alexandre Janniaux
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_SEMAPHOREIMPL_HPP
#define NAZARA_SEMAPHOREIMPL_HPP
#include <Nazara/Prerequisites.hpp>
#include <semaphore.h>
namespace Nz
{
class SemaphoreImpl
{
public:
SemaphoreImpl(unsigned int count);
~SemaphoreImpl();
unsigned int GetCount() const;
void Post();
void Wait();
bool Wait(UInt32 timeout);
private:
sem_t m_semaphore;
};
}
#endif // NAZARA_SEMAPHOREIMPL_HPP

View File

@@ -1,78 +0,0 @@
// Copyright (C) 2015 Alexandre Janniaux
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Posix/ThreadImpl.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/Functor.hpp>
#include <Nazara/Core/String.hpp>
#include <errno.h>
#include <sched.h>
#include <time.h>
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
ThreadImpl::ThreadImpl(Functor* functor)
{
int error = pthread_create(&m_handle, nullptr, &ThreadImpl::ThreadProc, functor);
if (error != 0)
NazaraInternalError("Failed to create thread: " + Error::GetLastSystemError());
}
void ThreadImpl::Detach()
{
pthread_detach(m_handle);
}
void ThreadImpl::Join()
{
pthread_join(m_handle, nullptr);
}
void ThreadImpl::SetName(const Nz::String& name)
{
#ifdef __GNUC__
pthread_setname_np(m_handle, name.GetConstBuffer());
#else
NazaraWarning("Setting thread name is not supported on this platform");
#endif
}
void ThreadImpl::SetCurrentName(const Nz::String& name)
{
#ifdef __GNUC__
pthread_setname_np(pthread_self(), name.GetConstBuffer());
#else
NazaraWarning("Setting current thread name is not supported on this platform");
#endif
}
void ThreadImpl::Sleep(UInt32 time)
{
if (time == 0)
sched_yield();
else
{
struct timespec ts;
ts.tv_sec = time / 1000;
ts.tv_nsec = (time - ts.tv_sec * 1000) * 1'000'000;
int r;
do
{
r = nanosleep(&ts, &ts);
}
while (r == -1 && errno == EINTR);
}
}
void* ThreadImpl::ThreadProc(void* userdata)
{
Functor* func = static_cast<Functor*>(userdata);
func->Run();
delete func;
return nullptr;
}
}

View File

@@ -1,42 +0,0 @@
// Copyright (C) 2015 Alexandre Janniaux
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_THREADIMPL_HPP
#define NAZARA_THREADIMPL_HPP
#include <Nazara/Prerequisites.hpp>
#if defined(__GNUC__) && !defined(_GNU_SOURCE)
#define _GNU_SOURCE
#endif
#include <pthread.h>
namespace Nz
{
struct Functor;
class String;
class ThreadImpl
{
public:
ThreadImpl(Functor* threadFunc);
void Detach();
void Join();
void SetName(const Nz::String& name);
static void SetCurrentName(const Nz::String& name);
static void Sleep(UInt32 time);
private:
static void* ThreadProc(void* userdata);
pthread_t m_handle;
};
}
#endif // NAZARA_THREADIMPL_HPP

View File

@@ -20,7 +20,7 @@ namespace Nz
* \return A reference to the path
*/
const String& Resource::GetFilePath() const
const std::filesystem::path& Resource::GetFilePath() const
{
return m_filePath;
}
@@ -31,7 +31,7 @@ namespace Nz
* \param filePath Path to the resource
*/
void Resource::SetFilePath(const String& filePath)
void Resource::SetFilePath(const std::filesystem::path& filePath)
{
m_filePath = filePath;
}

View File

@@ -1,86 +0,0 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Semaphore.hpp>
#if defined(NAZARA_PLATFORM_WINDOWS)
#include <Nazara/Core/Win32/SemaphoreImpl.hpp>
#elif defined(NAZARA_PLATFORM_POSIX)
#include <Nazara/Core/Posix/SemaphoreImpl.hpp>
#else
#error Lack of implementation: Semaphore
#endif
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
/*!
* \ingroup core
* \class Nz::Semaphore
* \brief Core class that represents a counting semaphore
*/
/*!
* \brief Constructs a semaphore object with a count
*/
Semaphore::Semaphore(unsigned int count)
{
m_impl = new SemaphoreImpl(count);
}
/*!
* \brief Destructs the object
*/
Semaphore::~Semaphore()
{
delete m_impl;
}
/*!
* \brief Gets the number of count that can handle the semaphore
* \return Number of count associated with the semaphore
*/
unsigned int Semaphore::GetCount() const
{
return m_impl->GetCount();
}
/*!
* \brief Increments the count of the semaphore and wait if count equals zero
*
* Increments the value of semaphore variable by 1. After the increment, if the pre-increment value was negative (meaning there are processes waiting for a resource), it transfers a blocked process from the semaphore's waiting queue to the ready queue
*/
void Semaphore::Post()
{
m_impl->Post();
}
/*!
* \brief Decrements the count of the semaphore and wait if count equals zero
*
* If the value of semaphore variable is not negative, decrements it by 1. If the semaphore variable is now negative, the process executing Wait is blocked (i.e., added to the semaphore's queue) until the value is greater or equal to 1. Otherwise, the process continues execution, having used a unit of the resource
*/
void Semaphore::Wait()
{
m_impl->Wait();
}
/*!
* \brief Decrements the count of the semaphore and wait if count equals zero
* \return true if the semaphore successfully decrements before timeout
*
* If the value of semaphore variable is not negative, decrements it by 1. If the semaphore variable is now negative, the process executing Wait is blocked (i.e., added to the semaphore's queue) until the value is greater or equal to 1. Otherwise, the process continues execution, having used a unit of the resource
*/
bool Semaphore::Wait(UInt32 timeout)
{
return m_impl->Wait(timeout);
}
}

View File

@@ -28,9 +28,9 @@ namespace Nz
* \return Empty string (meant to be virtual)
*/
String Stream::GetDirectory() const
std::filesystem::path Stream::GetDirectory() const
{
return String();
return std::filesystem::path();
}
/*!
@@ -38,9 +38,9 @@ namespace Nz
* \return Empty string (meant to be virtual)
*/
String Stream::GetPath() const
std::filesystem::path Stream::GetPath() const
{
return String();
return std::filesystem::path();
}
/*!
@@ -57,9 +57,9 @@ namespace Nz
* \remark With the text stream option, "\r\n" is treated as "\n"
* \remark The line separator character is not returned as part of the string
*/
String Stream::ReadLine(unsigned int lineSize)
std::string Stream::ReadLine(unsigned int lineSize)
{
String line;
std::string line;
if (lineSize == 0) // Maximal size undefined
{
const unsigned int bufferSize = 64;
@@ -79,9 +79,9 @@ namespace Nz
if (ptr != buffer)
{
if (m_streamOptions & StreamOption_Text && buffer[pos - 1] == '\r')
line.Append(buffer, pos - 1);
line.append(buffer, pos - 1);
else
line.Append(buffer, pos);
line.append(buffer, pos);
}
if (!SetCursorPos(GetCursorPos() - readSize + pos + 1))
@@ -100,28 +100,28 @@ namespace Nz
length--;
}
line.Append(buffer, length);
line.append(buffer, length);
}
}
while (readSize == bufferSize);
}
else
{
line.Set(lineSize, '\0');
line.resize(lineSize, '\0');
std::size_t readSize = Read(&line[0], lineSize);
std::size_t pos = line.Find('\n');
std::size_t pos = line.find('\n');
if (pos <= readSize) // False only if the character is not available (npos being the biggest integer)
{
if (m_streamOptions & StreamOption_Text && pos > 0 && line[pos - 1] == '\r')
line.Resize(pos);
line.resize(pos);
else
line.Resize(pos + 1);
line.resize(pos + 1);
if (!SetCursorPos(GetCursorPos() - readSize + pos + 1))
NazaraWarning("Failed to reset cursos pos");
}
else
line.Resize(readSize);
line.resize(readSize);
}
return line;

View File

@@ -0,0 +1,226 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/StringExt.hpp>
#include <Nazara/Core/Algorithm.hpp>
#include <Utfcpp/utf8.h>
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
namespace
{
bool IsSpace(char32_t character)
{
return character == '\t' || Unicode::GetCategory(character) & Unicode::Category_Separator;
}
char ToLower(char character)
{
if (character >= 'A' && character <= 'Z')
return character + ('a' - 'A');
else
return character;
}
char ToUpper(char character)
{
if (character >= 'a' && character <= 'z')
return character + ('A' - 'a');
else
return character;
}
template<std::size_t S>
struct WideConverter
{
static std::string From(const wchar_t* wstr, std::size_t size)
{
if constexpr (S == 2)
{
// UTF-16 (Windows)
return FromUtf16String(std::u16string_view(reinterpret_cast<const char16_t*>(wstr), size));
}
else if constexpr (S == 4)
{
// UTF-32 (Linux)
return FromUtf32String(std::u32string_view(reinterpret_cast<const char32_t*>(wstr), size));
}
else
{
static_assert(AlwaysFalse<S>, "Unsupported platform");
return std::string("<platform error>");
}
}
static std::wstring To(const std::string_view& str)
{
if constexpr (S == 2)
{
std::wstring result;
utf8::utf8to16(str.begin(), str.end(), std::back_inserter(result));
return result;
}
else if constexpr (S == 4)
{
std::wstring result;
utf8::utf8to32(str.begin(), str.end(), std::back_inserter(result));
return result;
}
else
{
static_assert(AlwaysFalse<S>, "Unsupported platform");
return std::string("<platform error>");
}
}
};
}
std::string FromUtf16String(const char16_t* u16str)
{
std::size_t size = std::char_traits<char16_t>::length(u16str);
return FromUtf16String(std::u16string_view(u16str, size));
}
std::string FromUtf16String(const std::u16string_view& u16str)
{
std::string result;
utf8::utf16to8(u16str.begin(), u16str.end(), std::back_inserter(result));
return result;
}
std::string FromUtf32String(const char32_t* u32str)
{
std::size_t size = std::char_traits<char32_t>::length(u32str);
return FromUtf32String(std::u32string_view(u32str, size));
}
std::string FromUtf32String(const std::u32string_view& u32str)
{
std::string result;
utf8::utf32to8(u32str.begin(), u32str.end(), std::back_inserter(result));
return result;
}
std::string FromWideString(const wchar_t* wstr)
{
std::size_t size = std::char_traits<wchar_t>::length(wstr);
return WideConverter<sizeof(wchar_t)>::From(wstr, size);
}
std::string FromWideString(const std::wstring_view& wstr)
{
return WideConverter<sizeof(wchar_t)>::From(wstr.data(), wstr.size());
}
bool StartsWith(const std::string_view& str, const std::string_view& s, CaseIndependent)
{
if (s.size() > str.size())
return false;
return std::equal(str.begin(), str.begin() + s.size(), s.begin(), s.end(), [](char c1, char c2)
{
return ToLower(c1) == ToLower(c2);
});
}
bool StartsWith(const std::string_view& str, const std::string_view& s, CaseIndependent, UnicodeAware)
{
if (str.empty() || s.empty())
return str == s;
utf8::iterator<const char*> it(str.data(), str.data(), str.data() + str.size());
utf8::iterator<const char*> it2(s.data(), s.data(), s.data() + s.size());
do
{
if (it2.base() >= s.data() + s.size())
return true;
if (Unicode::GetLowercase(*it) != Unicode::GetLowercase(*it2))
return false;
++it2;
}
while (*it++);
return true;
}
std::string ToLower(const std::string_view& str)
{
std::string result;
result.reserve(str.size());
std::transform(str.begin(), str.end(), std::back_inserter(result), Overload<char>(ToLower));
return result;
}
std::string ToLower(const std::string_view& str, UnicodeAware)
{
if (str.empty())
return std::string();
std::string result;
result.reserve(str.size());
utf8::unchecked::iterator<const char*> it(str.data());
do
utf8::append(Unicode::GetLowercase(*it), std::back_inserter(result));
while (*++it);
return result;
}
std::string ToUpper(const std::string_view& str)
{
std::string result;
result.reserve(str.size());
std::transform(str.begin(), str.end(), std::back_inserter(result), Overload<char>(ToUpper));
return result;
}
std::string ToUpper(const std::string_view& str, UnicodeAware)
{
if (str.empty())
return std::string();
std::string result;
result.reserve(str.size());
utf8::iterator<const char*> it(str.data(), str.data(), str.data() + str.size());
do
utf8::append(Unicode::GetUppercase(*it), std::back_inserter(result));
while (*++it);
return result;
}
std::u16string ToUtf16String(const std::string_view& str)
{
std::u16string result;
utf8::utf8to16(str.begin(), str.end(), std::back_inserter(result));
return result;
}
std::u32string ToUtf32String(const std::string_view& str)
{
std::u32string result;
utf8::utf8to32(str.begin(), str.end(), std::back_inserter(result));
return result;
}
std::wstring ToWideString(const std::string_view& str)
{
return WideConverter<sizeof(wchar_t)>::To(str);
}
}
#include <Nazara/Core/DebugOff.hpp>

View File

@@ -1,280 +0,0 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Thread.hpp>
#include <Nazara/Core/Config.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/HardwareInfo.hpp>
#include <Nazara/Core/MovablePtr.hpp>
#include <ostream>
#if defined(NAZARA_PLATFORM_WINDOWS)
#include <Nazara/Core/Win32/ThreadImpl.hpp>
#elif defined(NAZARA_PLATFORM_POSIX)
#include <Nazara/Core/Posix/ThreadImpl.hpp>
#else
#error Thread has no implementation
#endif
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
/*!
* \ingroup core
* \class Nz::Thread
* \brief Core class that represents a thread
*/
/*!
* \brief Constructs a Thread<T> object by default
*/
Thread::Thread() :
m_impl(nullptr)
{
}
/*!
* \brief Waits that the thread ends and then destroys this
*/
Thread::~Thread()
{
if (m_impl)
{
m_impl->Join();
delete m_impl;
m_impl = nullptr;
}
}
/*!
* \brief Detaches the thread
*/
void Thread::Detach()
{
if (m_impl)
{
m_impl->Detach();
delete m_impl;
m_impl = nullptr;
}
}
/*!
* \brief Gets the id of the thread
* \return The identifiant of the thread (PID)
*/
Thread::Id Thread::GetId() const
{
return Thread::Id(m_impl);
}
/*!
* \brief Checks whether the thread can be joined
* \return true if well formed and not detached
*/
bool Thread::IsJoinable() const
{
return m_impl != nullptr;
}
/*!
* \brief Waits that the thread ends
*
* \remark Produce a NazaraError if no functor was assigned and NAZARA_CORE_SAFE is defined
*/
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;
}
/*!
* \brief Changes the debugging name associated to a thread
*
* Changes the debugging name associated with a particular thread, and may helps with debugging tools.
*
* \param name The new name of the thread
*
* \remark Due to system limitations, thread name cannot exceed 15 characters (excluding null-terminator)
*
* \see SetCurrentThreadName
*/
void Thread::SetName(const String& name)
{
NazaraAssert(m_impl, "Invalid thread");
NazaraAssert(name.GetSize() < 16, "Thread name is too long");
m_impl->SetName(name);
}
/*!
* \brief Gets the number of simulatenous threads that can run on the same cpu
* \return The number of simulatenous threads
*/
unsigned int Thread::HardwareConcurrency()
{
return HardwareInfo::GetProcessorCount();
}
/*!
* \brief Changes the debugging name associated to the calling thread
*
* Changes the debugging name associated with the calling thread, and may helps with debugging tools.
*
* \param name The new name associated with this thread
*
* \remark Due to system limitations, thread name cannot exceed 15 characters (excluding null-terminator)
*
* \see SetName
*/
void Thread::SetCurrentThreadName(const String& name)
{
NazaraAssert(name.GetSize() < 16, "Thread name is too long");
ThreadImpl::SetCurrentName(name);
}
/*!
* \brief Makes sleep this thread
*
* \param milliseconds The number of milliseconds to sleep
*/
void Thread::Sleep(UInt32 milliseconds)
{
ThreadImpl::Sleep(milliseconds);
}
/*!
* \brief Creates the implementation of this thread
*
* \param functor The task the thread will represent
*/
void Thread::CreateImpl(Functor* functor)
{
m_impl = new ThreadImpl(functor);
}
/*********************************Thread::Id********************************/
/*!
* \brief Constructs a Thread<T> object with a thread implementation
*
* \param thread Thread implementation assigned to the thread
*/
Thread::Id::Id(ThreadImpl* thread) :
m_id(thread)
{
}
/*!
* \brief Compares two Thread::Id
* \return true if the two thread ids are the same
*
* \param lhs First id
* \param rhs Second id
*/
bool operator==(const Thread::Id& lhs, const Thread::Id& rhs)
{
return lhs.m_id == rhs.m_id;
}
/*!
* \brief Compares two Thread::Id
* \return false if the two thread ids are the same
*
* \param lhs First id
* \param rhs Second id
*/
bool operator!=(const Thread::Id& lhs, const Thread::Id& rhs)
{
return lhs.m_id != rhs.m_id;
}
/*!
* \brief Compares two Thread::Id
* \return true if the first thread id is inferior to the second one
*
* \param lhs First id
* \param rhs Second id
*/
bool operator<(const Thread::Id& lhs, const Thread::Id& rhs)
{
return lhs.m_id < rhs.m_id;
}
/*!
* \brief Compares two Thread::Id
* \return true if the first thread id is inferior or equal to the second one
*
* \param lhs First id
* \param rhs Second id
*/
bool operator<=(const Thread::Id& lhs, const Thread::Id& rhs)
{
return lhs.m_id <= rhs.m_id;
}
/*!
* \brief Compares two Thread::Id
* \return true if the first thread id is superior to the second one
*
* \param lhs First id
* \param rhs Second id
*/
bool operator>(const Thread::Id& lhs, const Thread::Id& rhs)
{
return lhs.m_id > rhs.m_id;
}
/*!
* \brief Compares two Thread::Id
* \return true if the first thread id is superior or equal to the second one
*
* \param lhs First id
* \param rhs Second id
*/
bool operator>=(const Thread::Id& lhs, const Thread::Id& rhs)
{
return lhs.m_id >= rhs.m_id;
}
/*!
* \brief Output operator
* \return The stream
*
* \param out The stream
* \param id The thread id to output
*/
std::ostream& operator<<(std::ostream& o, const Nz::Thread::Id& id)
{
o << id.m_id;
return o;
}
}

View File

@@ -1,84 +0,0 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
// Source: http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
#include <Nazara/Core/Win32/ConditionVariableImpl.hpp>
#include <Nazara/Core/Win32/MutexImpl.hpp>
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
ConditionVariableImpl::ConditionVariableImpl()
{
#if NAZARA_CORE_WINDOWS_NT6
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_NT6
ConditionVariableImpl::~ConditionVariableImpl()
{
CloseHandle(m_events[BROADCAST]);
CloseHandle(m_events[SIGNAL]);
}
#endif
void ConditionVariableImpl::Signal()
{
#if NAZARA_CORE_WINDOWS_NT6
WakeConditionVariable(&m_cv);
#else
if (m_count > 0)
SetEvent(m_events[SIGNAL]);
#endif
}
void ConditionVariableImpl::SignalAll()
{
#if NAZARA_CORE_WINDOWS_NT6
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_NT6
return SleepConditionVariableCS(&m_cv, &mutex->m_criticalSection, timeout) == TRUE;
#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

@@ -1,53 +0,0 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
// http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
#pragma once
#ifndef NAZARA_CONDITIONVARIABLEIMPL_HPP
#define NAZARA_CONDITIONVARIABLEIMPL_HPP
#include <Nazara/Prerequisites.hpp>
#include <atomic>
#include <windows.h>
namespace Nz
{
class MutexImpl;
class ConditionVariableImpl
{
public:
ConditionVariableImpl();
#if NAZARA_CORE_WINDOWS_NT6
~ConditionVariableImpl() = default;
#else
~ConditionVariableImpl();
#endif
void Signal();
void SignalAll();
void Wait(MutexImpl* mutex);
bool Wait(MutexImpl* mutex, UInt32 timeout);
private:
#if NAZARA_CORE_WINDOWS_NT6
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

@@ -1,122 +0,0 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Win32/DirectoryImpl.hpp>
#include <Nazara/Core/Error.hpp>
#include <memory>
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
DirectoryImpl::DirectoryImpl(const Directory* parent)
{
NazaraUnused(parent);
}
void DirectoryImpl::Close()
{
FindClose(m_handle);
}
String DirectoryImpl::GetResultName() const
{
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
return false;
}
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

@@ -1,52 +0,0 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_DIRECTORYIMPL_HPP
#define NAZARA_DIRECTORYIMPL_HPP
#include <Nazara/Prerequisites.hpp>
#include <windows.h>
namespace Nz
{
class Directory;
class String;
class DirectoryImpl
{
public:
DirectoryImpl(const Directory* parent);
DirectoryImpl(const DirectoryImpl&) = delete;
DirectoryImpl(DirectoryImpl&&) = delete; ///TODO
~DirectoryImpl() = default;
void Close();
String GetResultName() const;
UInt64 GetResultSize() const;
bool IsResultDirectory() const;
bool NextResult();
bool Open(const String& dirPath);
DirectoryImpl& operator=(const DirectoryImpl&) = delete;
DirectoryImpl& operator=(DirectoryImpl&&) = delete; ///TODO
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

@@ -5,34 +5,39 @@
#include <Nazara/Core/Win32/DynLibImpl.hpp>
#include <Nazara/Core/DynLib.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/File.hpp>
#include <Nazara/Core/String.hpp>
#include <Nazara/Core/StringExt.hpp>
#include <memory>
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
DynLibImpl::DynLibImpl(DynLib* parent)
DynLibImpl::DynLibImpl(DynLib*) :
m_handle(nullptr)
{
NazaraUnused(parent);
}
DynLibFunc DynLibImpl::GetSymbol(const String& symbol, String* errorMessage) const
DynLibImpl::~DynLibImpl()
{
DynLibFunc sym = reinterpret_cast<DynLibFunc>(GetProcAddress(m_handle, symbol.GetConstBuffer()));
if (m_handle)
FreeLibrary(m_handle);
}
DynLibFunc DynLibImpl::GetSymbol(const char* symbol, std::string* errorMessage) const
{
DynLibFunc sym = reinterpret_cast<DynLibFunc>(GetProcAddress(m_handle, symbol));
if (!sym)
*errorMessage = Error::GetLastSystemError();
return sym;
}
bool DynLibImpl::Load(const String& libraryPath, String* errorMessage)
bool DynLibImpl::Load(const std::filesystem::path& libraryPath, std::string* errorMessage)
{
String path = libraryPath;
if (!path.EndsWith(".dll"))
std::filesystem::path path = libraryPath;
if (path.extension() != ".dll")
path += ".dll";
m_handle = LoadLibraryExW(path.GetWideString().data(), nullptr, (File::IsAbsolute(path)) ? LOAD_WITH_ALTERED_SEARCH_PATH : 0);
m_handle = LoadLibraryExW(ToWideString(path.generic_u8string()).data(), nullptr, (path.is_absolute()) ? LOAD_WITH_ALTERED_SEARCH_PATH : 0);
if (m_handle)
return true;
else
@@ -41,10 +46,4 @@ namespace Nz
return false;
}
}
void DynLibImpl::Unload()
{
FreeLibrary(m_handle);
}
}

View File

@@ -9,23 +9,21 @@
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Core/DynLib.hpp>
#include <filesystem>
#include <windows.h>
namespace Nz
{
class String;
class DynLibImpl
{
public:
DynLibImpl(DynLib* m_parent);
DynLibImpl(const DynLibImpl&) = delete;
DynLibImpl(DynLibImpl&&) = delete; ///TODO?
~DynLibImpl() = default;
~DynLibImpl();
DynLibFunc GetSymbol(const String& symbol, String* errorMessage) const;
bool Load(const String& libraryPath, String* errorMessage);
void Unload();
DynLibFunc GetSymbol(const char* symbol, std::string* errorMessage) const;
bool Load(const std::filesystem::path& libraryPath, std::string* errorMessage);
DynLibImpl& operator=(const DynLibImpl&) = delete;
DynLibImpl& operator=(DynLibImpl&&) = delete; ///TODO?

View File

@@ -5,6 +5,7 @@
#include <Nazara/Core/Win32/FileImpl.hpp>
#include <Nazara/Core/CallOnExit.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/StringExt.hpp>
#include <Nazara/Core/Win32/Time.hpp>
#include <memory>
#include <Nazara/Core/Debug.hpp>
@@ -18,9 +19,10 @@ namespace Nz
NazaraUnused(parent);
}
void FileImpl::Close()
FileImpl::~FileImpl()
{
CloseHandle(m_handle);
if (m_handle)
CloseHandle(m_handle);
}
bool FileImpl::EndOfFile() const
@@ -55,7 +57,7 @@ namespace Nz
return position.QuadPart;
}
bool FileImpl::Open(const String& filePath, OpenModeFlags mode)
bool FileImpl::Open(const std::filesystem::path& filePath, OpenModeFlags mode)
{
DWORD access = 0;
DWORD shareMode = FILE_SHARE_READ;
@@ -87,7 +89,7 @@ namespace Nz
if ((mode & OpenMode_Lock) == 0)
shareMode |= FILE_SHARE_WRITE;
m_handle = CreateFileW(filePath.GetWideString().data(), access, shareMode, nullptr, openMode, 0, nullptr);
m_handle = CreateFileW(ToWideString(filePath.generic_u8string()).data(), access, shareMode, nullptr, openMode, 0, nullptr);
return m_handle != INVALID_HANDLE_VALUE;
}
@@ -197,118 +199,4 @@ namespace Nz
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;
}
}
bool FileImpl::Delete(const String& filePath)
{
if (DeleteFileW(filePath.GetWideString().data()))
return true;
else
{
NazaraError("Failed to delete file (" + filePath + "): " + Error::GetLastSystemError());
return false;
}
}
bool FileImpl::Exists(const String& 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 FileImpl::GetCreationTime(const String& 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: " + 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

@@ -23,13 +23,12 @@ namespace Nz
FileImpl(const File* parent);
FileImpl(const FileImpl&) = delete;
FileImpl(FileImpl&&) = delete; ///TODO
~FileImpl() = default;
~FileImpl();
void Close();
bool EndOfFile() const;
void Flush();
UInt64 GetCursorPos() const;
bool Open(const String& filePath, OpenModeFlags mode);
bool Open(const std::filesystem::path& filePath, OpenModeFlags mode);
std::size_t Read(void* buffer, std::size_t size);
bool SetCursorPos(CursorPosition pos, Int64 offset);
bool SetSize(UInt64 size);
@@ -38,15 +37,6 @@ namespace Nz
FileImpl& operator=(const FileImpl&) = delete;
FileImpl& operator=(FileImpl&&) = delete; ///TODO
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;

View File

@@ -1,38 +0,0 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Win32/MutexImpl.hpp>
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
MutexImpl::MutexImpl()
{
#if NAZARA_CORE_WINDOWS_CS_SPINLOCKS > 0
InitializeCriticalSectionAndSpinCount(&m_criticalSection, NAZARA_CORE_WINDOWS_CS_SPINLOCKS);
#else
InitializeCriticalSection(&m_criticalSection);
#endif
}
MutexImpl::~MutexImpl()
{
DeleteCriticalSection(&m_criticalSection);
}
void MutexImpl::Lock()
{
EnterCriticalSection(&m_criticalSection);
}
bool MutexImpl::TryLock()
{
return TryEnterCriticalSection(&m_criticalSection) != 0;
}
void MutexImpl::Unlock()
{
LeaveCriticalSection(&m_criticalSection);
}
}

View File

@@ -1,32 +0,0 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_MUTEXIMPL_HPP
#define NAZARA_MUTEXIMPL_HPP
#include <Nazara/Prerequisites.hpp>
#include <windows.h>
namespace Nz
{
class MutexImpl
{
friend class ConditionVariableImpl;
public:
MutexImpl();
~MutexImpl();
void Lock();
bool TryLock();
void Unlock();
private:
CRITICAL_SECTION m_criticalSection;
};
}
#endif // NAZARA_MUTEXIMPL_HPP

View File

@@ -1,67 +0,0 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Win32/SemaphoreImpl.hpp>
#include <Nazara/Core/Config.hpp>
#include <Nazara/Core/Error.hpp>
#include <limits>
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
SemaphoreImpl::SemaphoreImpl(unsigned int count)
{
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
}
}

View File

@@ -1,31 +0,0 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#pragma once
#ifndef NAZARA_SEMAPHOREIMPL_HPP
#define NAZARA_SEMAPHOREIMPL_HPP
#include <Nazara/Prerequisites.hpp>
#include <windows.h>
namespace Nz
{
class SemaphoreImpl
{
public:
SemaphoreImpl(unsigned int count);
~SemaphoreImpl();
unsigned int GetCount() const;
void Post();
void Wait();
bool Wait(UInt32 timeout);
private:
HANDLE m_semaphore;
};
}
#endif // NAZARA_SEMAPHOREIMPL_HPP

View File

@@ -1,122 +0,0 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Win32/ThreadImpl.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Core/Functor.hpp>
#include <process.h>
#include <windows.h>
#include <Nazara/Core/Debug.hpp>
namespace Nz
{
// Windows 10, version 1607 brought SetThreadDescription in order to name a thread
using SetThreadDescriptionFunc = HRESULT(WINAPI*)(HANDLE hThread, PCWSTR lpThreadDescription);
#ifdef NAZARA_COMPILER_MSVC
namespace
{
#pragma pack(push,8)
struct THREADNAME_INFO
{
DWORD dwType;
LPCSTR szName;
DWORD dwThreadID;
DWORD dwFlags;
};
#pragma pack(pop)
}
#endif
ThreadImpl::ThreadImpl(Functor* functor)
{
unsigned int threadId;
m_handle = reinterpret_cast<HANDLE>(_beginthreadex(nullptr, 0, &ThreadImpl::ThreadProc, functor, 0, &threadId));
if (!m_handle)
NazaraInternalError("Failed to create thread: " + Error::GetLastSystemError());
m_threadId = threadId;
}
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);
}
void ThreadImpl::SetName(const Nz::String& name)
{
SetThreadName(m_handle, name);
}
void ThreadImpl::SetCurrentName(const Nz::String& name)
{
SetThreadName(::GetCurrentThread(), name);
}
void ThreadImpl::Sleep(UInt32 time)
{
::Sleep(time);
}
void ThreadImpl::RaiseThreadNameException(DWORD threadId, const char* threadName)
{
#ifdef NAZARA_COMPILER_MSVC
if (!::IsDebuggerPresent())
return;
// https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
constexpr DWORD MS_VC_EXCEPTION = 0x406D1388;
THREADNAME_INFO info;
info.dwType = 0x1000;
info.szName = threadName;
info.dwThreadID = threadId;
info.dwFlags = 0;
#pragma warning(push)
#pragma warning(disable: 6320 6322)
__try
{
RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), reinterpret_cast<ULONG_PTR*>(&info));
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
}
#pragma warning(pop)
#else
NazaraWarning("SetThreadDescription is not supported and threadname exception is only supported with MSVC");
#endif
}
void ThreadImpl::SetThreadName(HANDLE threadHandle, const Nz::String& name)
{
// Try to use SetThreadDescription if available
static SetThreadDescriptionFunc SetThreadDescription = reinterpret_cast<SetThreadDescriptionFunc>(::GetProcAddress(::GetModuleHandleW(L"Kernel32.dll"), "SetThreadDescription"));
if (SetThreadDescription)
SetThreadDescription(threadHandle, name.GetWideString().data());
else
RaiseThreadNameException(::GetThreadId(threadHandle), name.GetConstBuffer());
}
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;
}
}

View File

@@ -1,42 +0,0 @@
// Copyright (C) 2017 Jérôme Leclercq
// This file is part of the "Nazara Engine - Core module"
// For conditions of distribution and use, see copyright notice in Config.hpp
// Inspiré du code de la SFML par Laurent Gomila
#pragma once
#ifndef NAZARA_THREADIMPL_HPP
#define NAZARA_THREADIMPL_HPP
#include <Nazara/Prerequisites.hpp>
#include <Nazara/Core/String.hpp>
#include <windows.h>
namespace Nz
{
struct Functor;
class ThreadImpl
{
public:
ThreadImpl(Functor* threadFunc);
void Detach();
void Join();
void SetName(const Nz::String& name);
static void SetCurrentName(const Nz::String& name);
static void Sleep(UInt32 time);
private:
static void RaiseThreadNameException(DWORD threadId, const char* threadName);
static void SetThreadName(HANDLE threadHandle, const Nz::String& name);
static unsigned int __stdcall ThreadProc(void* userdata);
DWORD m_threadId;
HANDLE m_handle;
};
}
#endif // NAZARA_THREADIMPL_HPP