Former-commit-id: 6a6191171a34d24a22c020a8d4c01e7869c3279d
This commit is contained in:
Lynix
2016-02-24 14:19:21 +01:00
90 changed files with 7875 additions and 349 deletions

View File

@@ -17,8 +17,24 @@
namespace Nz
{
/*!
* \class Nz::AbstractHash<T>
* \brief Core class that represents the behaviour of the hash classes
*
* \remark This class is abstract
*/
AbstractHash::~AbstractHash() = default;
/*!
* \brief Factory of Hash classes in function of HashType
* \return A new instance of the Hash class according to the HashType
*
* \param type Enumeration of type HashType
*
* \remark If enumeration is not defined in HashType, a NazaraInternalError is thrown and nullptr is returned
*/
std::unique_ptr<AbstractHash> AbstractHash::Get(HashType type)
{
NazaraAssert(type <= HashType_Max, "Hash type value out of enum");
@@ -26,34 +42,34 @@ namespace Nz
switch (type)
{
case HashType_Fletcher16:
return std::unique_ptr<AbstractHash>(new HashFletcher16);
return std::make_unique<HashFletcher16>();
case HashType_CRC32:
return std::unique_ptr<AbstractHash>(new HashCRC32);
return std::make_unique<HashCRC32>();
case HashType_MD5:
return std::unique_ptr<AbstractHash>(new HashMD5);
return std::make_unique<HashMD5>();
case HashType_SHA1:
return std::unique_ptr<AbstractHash>(new HashSHA1);
return std::make_unique<HashSHA1>();
case HashType_SHA224:
return std::unique_ptr<AbstractHash>(new HashSHA224);
return std::make_unique<HashSHA224>();
case HashType_SHA256:
return std::unique_ptr<AbstractHash>(new HashSHA256);
return std::make_unique<HashSHA256>();
case HashType_SHA384:
return std::unique_ptr<AbstractHash>(new HashSHA384);
return std::make_unique<HashSHA384>();
case HashType_SHA512:
return std::unique_ptr<AbstractHash>(new HashSHA512);
return std::make_unique<HashSHA512>();
case HashType_Whirlpool:
return std::unique_ptr<AbstractHash>(new HashWhirlpool);
return std::make_unique<HashWhirlpool>();
}
NazaraInternalError("Hash type not handled (0x" + String::Number(type, 16) + ')');
return std::unique_ptr<AbstractHash>();
return nullptr;
}
}

View File

@@ -11,17 +11,34 @@ namespace Nz
namespace
{
const char* errorType[] = {
"Assert failed: ", // ErrorType_AssertFailed
"Internal error: ", // ErrorType_Internal
"Error: ", // ErrorType_Normal
"Warning: " // ErrorType_Warning
"Assert failed: ", // ErrorType_AssertFailed
"Internal error: ", // ErrorType_Internal
"Error: ", // ErrorType_Normal
"Warning: " // ErrorType_Warning
};
static_assert(sizeof(errorType) / sizeof(const char*) == ErrorType_Max + 1, "Error type array is incomplete");
}
/*!
* \class Nz::AbstractLogger<T>
* \brief Core class that represents the behaviour of the log classes
*
* \remark This class is abstract
*/
AbstractLogger::~AbstractLogger() = default;
/*!
* \brief Writes the error in StringStream
*
* \param type Enumeration of type ErrorType
* \param error String describing the error
* \param line Line number in the file
* \param file Filename
* \param function Name of the function throwing the error
*/
void AbstractLogger::WriteError(ErrorType type, const String& error, unsigned int line, const char* file, const char* function)
{
StringStream stream;

View File

@@ -9,6 +9,19 @@
namespace Nz
{
/*!
* \class Nz::ByteArray
* \brief Core class that represents an array of bytes
*/
/*!
* \brief Output operator
* \return The stream
*
* \param out The stream
* \param byteArray The ByteArray to output
*/
std::ostream& operator<<(std::ostream& out, const Nz::ByteArray& byteArray)
{
out << byteArray.ToHex();

View File

@@ -11,24 +11,61 @@
namespace Nz
{
/*!
* \class Nz::ByteStream
* \brief Core class that represents a stream of bytes
*/
/*!
* \brief Constructs a ByteStream object with a byte array
*
* \param byteArray Bytes to stream
* \param openMode Reading/writing mode for the stream
*/
ByteStream::ByteStream(ByteArray* byteArray, UInt32 openMode) :
ByteStream()
{
SetStream(byteArray, openMode);
}
/*!
* \brief Constructs a ByteStream object with a raw memory and a size
*
* \param ptr Pointer to raw memory
* \param size Size that can be read
*
* \remark If preallocated space of ptr is less than the size, the behaviour is undefined
*/
ByteStream::ByteStream(void* ptr, Nz::UInt64 size) :
ByteStream()
{
SetStream(ptr, size);
}
/*!
* \brief Constructs a ByteStream object with a raw memory and a size
*
* \param ptr Constant pointer to raw memory
* \param size Size that can be read
*
* \remark If preallocated space of ptr is less than the size, the behaviour is undefined
*/
ByteStream::ByteStream(const void* ptr, Nz::UInt64 size) :
ByteStream()
{
SetStream(ptr, size);
}
/*!
* \brief Sets this with a byte array
*
* \param byteArray Bytes to stream
* \param openMode Reading/writing mode for the stream
*/
void ByteStream::SetStream(ByteArray* byteArray, UInt32 openMode)
{
std::unique_ptr<Stream> stream(new MemoryStream(byteArray, openMode));
@@ -38,6 +75,15 @@ namespace Nz
m_ownedStream = std::move(stream);
}
/*!
* \brief Sets this with a raw memory and a size
*
* \param ptr Pointer to raw memory
* \param size Size that can be read
*
* \remark If preallocated space of ptr is less than the size, the behaviour is undefined
*/
void ByteStream::SetStream(void* ptr, Nz::UInt64 size)
{
std::unique_ptr<Stream> stream(new MemoryView(ptr, size));
@@ -47,6 +93,15 @@ namespace Nz
m_ownedStream = std::move(stream);
}
/*!
* \brief Sets this with a raw memory and a size
*
* \param ptr Constant pointer to raw memory
* \param size Size that can be read
*
* \remark If preallocated space of ptr is less than the size, the behaviour is undefined
*/
void ByteStream::SetStream(const void* ptr, Nz::UInt64 size)
{
std::unique_ptr<Stream> stream(new MemoryView(ptr, size));
@@ -56,6 +111,12 @@ namespace Nz
m_ownedStream = std::move(stream);
}
/*!
* \brief Signal function (meant to be virtual)
*
* \remark Produces a NazaraError
*/
void ByteStream::OnEmptyStream()
{
NazaraError("No stream");

View File

@@ -46,7 +46,7 @@ namespace Nz
* \brief Utility class that measure the elapsed time
*/
/*!
/*!
* \brief Constructs a Clock object
*
* \param startingValue The starting time value, in microseconds

View File

@@ -18,32 +18,84 @@
namespace Nz
{
/*!
* \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");

View File

@@ -13,12 +13,24 @@
namespace Nz
{
/*!
* \class Nz::CoreCore
* \brief Core class that represents the module initializer of Core
*/
/*!
* \brief Initializes the Core module
* \return true if initialization is successful
*
* \remark Produces a NazaraNotice
*/
bool Core::Initialize()
{
if (s_moduleReferenceCounter > 0)
{
s_moduleReferenceCounter++;
return true; // Déjà initiali
return true; // Already initialized
}
s_moduleReferenceCounter++;
@@ -29,23 +41,34 @@ namespace Nz
return true;
}
/*!
* \brief Checks whether the module is initialized
* \return true if module is initialized
*/
bool Core::IsInitialized()
{
return s_moduleReferenceCounter != 0;
}
/*!
* \brief Uninitializes the Core module
*
* \remark Produces a NazaraNotice
*/
void Core::Uninitialize()
{
if (s_moduleReferenceCounter != 1)
{
// Le module est soit encore utilisé, soit pas initiali
// The module is still in use, or can not be uninitialized
if (s_moduleReferenceCounter > 1)
s_moduleReferenceCounter--;
return;
}
// Libération du module
// Free of module
s_moduleReferenceCounter = 0;
HardwareInfo::Uninitialize();

View File

@@ -30,16 +30,31 @@ namespace Nz
{
namespace
{
//FIXME: MinGW seems to dislike thread_local shared_ptr.. (using a std::string is a working hackfix)
//FIXME: MinGW seems to dislike thread_local shared_ptr.. (using a std::string is a working hackfix)
thread_local std::string currentPath(DirectoryImpl::GetCurrent());
}
/*!
* \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('*'),
@@ -47,11 +62,21 @@ namespace Nz
{
}
/*!
* \brief Destructs the object and calls Close
*
* \see Close
*/
Directory::~Directory()
{
Close();
}
/*!
* \brief Closes the directory
*/
void Directory::Close()
{
NazaraLock(m_mutex);
@@ -64,16 +89,26 @@ namespace Nz
}
}
/*!
* \brief Checks whether the directory exists
* \return true if directory exists
*/
bool Directory::Exists() const
{
NazaraLock(m_mutex);
if (IsOpen())
return true; // Le fichier est ouvert, donc il existe
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);
@@ -81,6 +116,11 @@ namespace Nz
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);
@@ -88,12 +128,19 @@ namespace Nz
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 (!m_impl)
if (!IsOpen())
{
NazaraError("Directory not opened");
return String();
@@ -103,12 +150,19 @@ namespace Nz
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 (!m_impl)
if (!IsOpen())
{
NazaraError("Directory not opened");
return String();
@@ -118,12 +172,19 @@ namespace Nz
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 (!m_impl)
if (!IsOpen())
{
NazaraError("Directory not opened");
return 0;
@@ -133,6 +194,11 @@ namespace Nz
return m_impl->GetResultSize();
}
/*!
* \brief Checks whether the directory is open
* \return true if open
*/
bool Directory::IsOpen() const
{
NazaraLock(m_mutex);
@@ -140,12 +206,19 @@ namespace Nz
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 (!m_impl)
if (!IsOpen())
{
NazaraError("Directory not opened");
return false;
@@ -155,12 +228,21 @@ namespace Nz
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 (!m_impl)
if (!IsOpen())
{
NazaraError("Directory not opened");
return false;
@@ -185,6 +267,11 @@ namespace Nz
return true;
}
/*!
* \brief Opens the directory
* \return true if opening is successful
*/
bool Directory::Open()
{
NazaraLock(m_mutex);
@@ -206,6 +293,12 @@ namespace Nz
return true;
}
/*!
* \brief Sets the path of the directory
*
* \param dirPath Path of the directory
*/
void Directory::SetPath(const String& dirPath)
{
NazaraLock(m_mutex);
@@ -215,6 +308,12 @@ namespace Nz
m_dirPath = File::AbsolutePath(dirPath);
}
/*!
* \brief Sets the pattern of the directory
*
* \param dirPath Pattern of the directory
*/
void Directory::SetPattern(const String& pattern)
{
NazaraLock(m_mutex);
@@ -222,6 +321,18 @@ namespace Nz
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 targetPath 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())
@@ -262,6 +373,14 @@ namespace Nz
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())
@@ -275,7 +394,7 @@ namespace Nz
return false;
#ifdef NAZARA_PLATFORM_WINDOWS
// Contrairement au disque (Ex: "C:"), le chemin réseau n'est pas considéré comme un dossier (Ex: "\\Laptop")
// Unlike to disk (Ex: "C:"), the netwrok path is not considered as a directory (Ex: "\\Laptop")
if (path.Match("\\\\*"))
{
foundPos = path.Find('\\', 2);
@@ -309,6 +428,13 @@ namespace Nz
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())
@@ -317,14 +443,24 @@ namespace Nz
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: Est-ce que cette méthode est au bon endroit ?
///FIXME: Is this method in the right place ?
const char* ptr = std::strstr(currentFile, "NazaraEngine/");
if (!ptr)
ptr = std::strstr(currentFile, "NazaraEngine\\");
@@ -335,6 +471,14 @@ namespace Nz
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())
@@ -344,7 +488,7 @@ namespace Nz
{
Directory dir(dirPath);
if (!dir.Open())
return DirectoryImpl::Remove(dirPath); // Si on n'arrive pas à ouvrir le dossier, on tente de le supprimer
return DirectoryImpl::Remove(dirPath); // If we can't open the directory, we try to delete it
while (dir.NextResult(true))
{
@@ -366,6 +510,13 @@ namespace Nz
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);
@@ -376,5 +527,5 @@ namespace Nz
}
else
return false;
}
}
}

View File

@@ -25,11 +25,26 @@
namespace Nz
{
/*!
* \class Nz::DynLib
* \brief Core class that represents a dynamic library loader
*/
/*!
* \brief Constructs a DynLib object by default
*/
DynLib::DynLib() :
m_impl(nullptr)
{
}
/*!
* \brief Constructs a DynLib object by move semantic
*
* \param lib DynLib to move into this
*/
DynLib::DynLib(DynLib&& lib) :
m_lastError(std::move(lib.m_lastError)),
m_impl(lib.m_impl)
@@ -37,11 +52,22 @@ namespace Nz
lib.m_impl = nullptr;
}
/*!
* \brief Destructs the object and calls Unload
*
* \see Unload
*/
DynLib::~DynLib()
{
Unload();
}
/*!
* \brief Gets the last error
* \return Last error
*/
String DynLib::GetLastError() const
{
NazaraLock(m_mutex)
@@ -49,12 +75,19 @@ namespace Nz
return m_lastError;
}
/*!
* \brief Gets the symbol for the name
* \return Function which is the symbol of the function name
*
* \remark Produces a NazaraError if library is not loaded with NAZARA_CORE_SAFE defined
*/
DynLibFunc DynLib::GetSymbol(const String& symbol) const
{
NazaraLock(m_mutex)
#if NAZARA_CORE_SAFE
if (!m_impl)
if (!IsLoaded())
{
NazaraError("Library not opened");
return nullptr;
@@ -64,11 +97,25 @@ namespace Nz
return m_impl->GetSymbol(symbol, &m_lastError);
}
/*!
* \brief Checks whether the library is loaded
* \return true if loaded
*/
bool DynLib::IsLoaded() const
{
return m_impl != nullptr;
}
/*!
* \brief Loads the library with that path
* \return true if loading is successful
*
* \param libraryPath Path of the library
*
* \remark Produces a NazaraError if library is could not be loaded
*/
bool DynLib::Load(const String& libraryPath)
{
NazaraLock(m_mutex)
@@ -87,11 +134,15 @@ namespace Nz
return true;
}
/*!
* \brief Unloads the library
*/
void DynLib::Unload()
{
NazaraLock(m_mutex)
if (m_impl)
if (IsLoaded())
{
m_impl->Unload();
delete m_impl;
@@ -99,6 +150,13 @@ namespace Nz
}
}
/*!
* \brief Moves the other lib into this
* \return A reference to this
*
* \param lib DynLib to move in this
*/
DynLib& DynLib::operator=(DynLib&& lib)
{
Unload();

View File

@@ -18,11 +18,30 @@
namespace Nz
{
/*!
* \class Nz::Error
* \brief Core class that represents an error
*/
/*!
* \brief Gets the flags of the error
* \return Flag
*/
UInt32 Error::GetFlags()
{
return s_flags;
}
/*!
* \brief Gets the last error
* \return Last error
*
* \param file Optional argument to set last error file
* \param line Optional argument to set last error line
* \param function Optional argument to set last error function
*/
String Error::GetLastError(const char** file, unsigned int* line, const char** function)
{
if (file)
@@ -37,6 +56,11 @@ namespace Nz
return s_lastError;
}
/*!
* \brief Gets the last system error code
* \return "errno"
*/
unsigned int Error::GetLastSystemErrorCode()
{
#if defined(NAZARA_PLATFORM_WINDOWS)
@@ -49,6 +73,13 @@ namespace Nz
#endif
}
/*!
* \brief Gets the string representation of the last system error code
* \return Message of the error
*
* \param code Code of the error
*/
String Error::GetLastSystemError(unsigned int code)
{
#if defined(NAZARA_PLATFORM_WINDOWS)
@@ -65,7 +96,7 @@ namespace Nz
String error(String::Unicode(buffer));
LocalFree(buffer);
error.Trim(); // Pour une raison inconnue, Windows met deux-trois retours à la ligne après le message
error.Trim(); // For an unknown reason, Windows put two-three line return after the message
return error;
#elif defined(NAZARA_PLATFORM_POSIX)
@@ -77,11 +108,27 @@ namespace Nz
#endif
}
/*!
* \brief Sets the flags
*
* \param flags Flags for the error
*/
void Error::SetFlags(UInt32 flags)
{
s_flags = flags;
}
/*!
* \brief Checks if the error should trigger
*
* \param type ErrorType of the error
* \param error Message of the error
*
* \remark Produces a std::abort on AssertFailed with NAZARA_CORE_EXIT_ON_ASSERT_FAILURE defined
* \remark Produces a std::runtime_error on AssertFailed or throwing exception
*/
void Error::Trigger(ErrorType type, const String& error)
{
if (type == ErrorType_AssertFailed || (s_flags & ErrorFlag_Silent) == 0 || (s_flags & ErrorFlag_SilentDisabled) != 0)
@@ -102,6 +149,19 @@ namespace Nz
throw std::runtime_error(error);
}
/*!
* \brief Checks if the error should trigger
*
* \param type ErrorType of the error
* \param error Message of the error
* \param line Line of the error
* \param file File of the error
* \param function Function of the error
*
* \remark Produces a std::abort on AssertFailed with NAZARA_CORE_EXIT_ON_ASSERT_FAILURE defined
* \remark Produces a std::runtime_error on AssertFailed or throwing exception
*/
void Error::Trigger(ErrorType type, const String& error, unsigned int line, const char* file, const char* function)
{
if (type == ErrorType_AssertFailed || (s_flags & ErrorFlag_Silent) == 0 || (s_flags & ErrorFlag_SilentDisabled) != 0)

View File

@@ -8,22 +8,50 @@
namespace Nz
{
/*!
* \class Nz::ErrorFlags
* \brief Core class that represents flags for error
*/
/*!
* \brief Constructs a ErrorFlags object with flags
*
* \param flags Flags for the error
* \param replace Replace the entirely the old flag if true, else do a "OR"
*/
ErrorFlags::ErrorFlags(UInt32 flags, bool replace) :
m_previousFlags(Error::GetFlags())
{
SetFlags(flags, replace);
}
/*!
* \brief Destructs the object and sets the old flag
*/
ErrorFlags::~ErrorFlags()
{
Error::SetFlags(m_previousFlags);
}
/*!
* \brief Gets the previous flag
* \return Previous flag
*/
UInt32 ErrorFlags::GetPreviousFlags() const
{
return m_previousFlags;
}
/*!
* \brief Sets the flags
*
* \param flags Flags for the error
* \param replace Replace the entirely the old flag if true, else do a "OR"
*/
void ErrorFlags::SetFlags(UInt32 flags, bool replace)
{
if (!replace)

View File

@@ -30,23 +30,51 @@
namespace Nz
{
/*!
* \class Nz::File
* \brief Core class that represents a file
*/
/*!
* \brief Constructs a File object by default
*/
File::File() :
m_impl(nullptr)
{
}
/*!
* \brief Constructs a File object with a file path
*
* \param filePath Path to the file
*/
File::File(const String& filePath) :
File()
{
SetFile(filePath);
}
/*!
* \brief Constructs a File object with a file path and flags
*
* \param filePath Path to the file
* \param openMode Flag of the file
*/
File::File(const String& filePath, UInt32 openMode) :
File()
{
Open(filePath, openMode);
}
/*!
* \brief Constructs a File object by move semantic
*
* \param file File to move into this
*/
File::File(File&& file) noexcept :
Stream(std::move(file)),
m_filePath(std::move(file.m_filePath)),
@@ -55,16 +83,33 @@ namespace Nz
file.m_impl = nullptr;
}
/*!
* \brief Destructs the object and calls Close
*
* \see Close
*/
File::~File()
{
Close();
}
/*!
* \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)
{
return Copy(m_filePath, newFilePath);
}
/*!
* \brief Closes the file
*/
void File::Close()
{
NazaraLock(m_mutex)
@@ -79,6 +124,11 @@ namespace Nz
}
}
/*!
* \brief Deletes the file
* \return true if delete is successful
*/
bool File::Delete()
{
NazaraLock(m_mutex)
@@ -88,6 +138,13 @@ namespace Nz
return Delete(m_filePath);
}
/*!
* \brief Checks whether the file has reached the end
* \return true if cursor is at the end of the file
*
* \remark Produces a NazaraError if file is not open with NAZARA_CORE_SAFE defined
*/
bool File::EndOfFile() const
{
NazaraLock(m_mutex)
@@ -95,7 +152,7 @@ namespace Nz
#if NAZARA_CORE_SAFE
if (!IsOpen())
{
NazaraError("File not opened");
NazaraError("File not open");
return false;
}
#endif
@@ -103,11 +160,25 @@ namespace Nz
return m_impl->EndOfFile();
}
/*!
* \brief Checks whether the file has reached the end of the stream
* \return true if cursor is at the end of the file
*
* \remark Produces a NazaraError if file is not open with NAZARA_CORE_SAFE defined
*
* \see EndOfFile
*/
bool File::EndOfStream() const
{
return EndOfFile();
}
/*!
* \brief Checks whether the file exists
* \return true if file exists
*/
bool File::Exists() const
{
NazaraLock(m_mutex)
@@ -118,6 +189,11 @@ namespace Nz
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)
@@ -125,15 +201,27 @@ namespace Nz
return GetCreationTime(m_filePath);
}
/*!
* \brief Gets the position of the cursor in the file
* \return Position of the cursor
*
* \remark Produces a NazaraAssert if file is not open
*/
UInt64 File::GetCursorPos() const
{
NazaraLock(m_mutex)
NazaraAssert(IsOpen(), "File is not opened");
NazaraAssert(IsOpen(), "File is not open");
return m_impl->GetCursorPos();
}
/*!
* \brief Gets the directory of the file
* \return Directory of the file
*/
String File::GetDirectory() const
{
NazaraLock(m_mutex)
@@ -141,6 +229,11 @@ namespace Nz
return m_filePath.SubStringTo(NAZARA_DIRECTORY_SEPARATOR, -1, true, true);
}
/*!
* \brief Gets the name of the file
* \return Name of the file
*/
String File::GetFileName() const
{
NazaraLock(m_mutex)
@@ -148,6 +241,11 @@ namespace Nz
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)
@@ -155,6 +253,11 @@ namespace Nz
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)
@@ -162,6 +265,11 @@ namespace Nz
return GetLastWriteTime(m_filePath);
}
/*!
* \brief Gets the path of the file
* \return Path of the file
*/
String File::GetPath() const
{
NazaraLock(m_mutex)
@@ -169,6 +277,11 @@ namespace Nz
return m_filePath;
}
/*!
* \brief Gets the size of the file
* \return Size of the file
*/
UInt64 File::GetSize() const
{
NazaraLock(m_mutex)
@@ -176,6 +289,11 @@ namespace Nz
return GetSize(m_filePath);
}
/*!
* \brief Checks whether the file is open
* \return true if open
*/
bool File::IsOpen() const
{
NazaraLock(m_mutex)
@@ -183,22 +301,14 @@ namespace Nz
return m_impl != nullptr;
}
bool File::Rename(const String& newFilePath)
{
NazaraLock(m_mutex)
bool opened = IsOpen();
Close();
bool success = Rename(m_filePath, newFilePath);
if (success)
m_filePath = NormalizePath(newFilePath);
if (opened)
Open();
return success;
}
/*!
* \brief Opens the file with flags
* \return true if opening is successful
*
* \param openMode Flag for file
*
* \remark Produces a NazaraError if OS error to open a file
*/
bool File::Open(unsigned int openMode)
{
@@ -215,7 +325,7 @@ namespace Nz
std::unique_ptr<FileImpl> impl(new FileImpl(this));
if (!impl->Open(m_filePath, openMode))
{
ErrorFlags flags(ErrorFlag_Silent); // Silencieux par défaut
ErrorFlags flags(ErrorFlag_Silent); // Silent by default
NazaraError("Failed to open \"" + m_filePath + "\": " + Error::GetLastSystemError());
return false;
}
@@ -231,6 +341,16 @@ namespace Nz
return true;
}
/*!
* \brief Opens the file with file path and flags
* \return true if opening is successful
*
* \param filePath Path to the file
* \param openMode Flag for file
*
* \remark Produces a NazaraError if OS error to open a file
*/
bool File::Open(const String& filePath, unsigned int openMode)
{
NazaraLock(m_mutex)
@@ -241,24 +361,72 @@ namespace Nz
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
*
* \param pos Position of the cursor
* \param offset Offset according to the cursor position
*
* \remark Produces a NazaraAssert if file is not open
*/
bool File::SetCursorPos(CursorPosition pos, Int64 offset)
{
NazaraLock(m_mutex)
NazaraAssert(IsOpen(), "File is not opened");
NazaraAssert(IsOpen(), "File is not open");
return m_impl->SetCursorPos(pos, offset);
}
/*!
* \brief Sets the position of the cursor
* \return true if cursor is successfully positioned
*
* \param offset Offset according to the cursor begin position
*
* \remark Produces a NazaraAssert if file is not open
*/
bool File::SetCursorPos(UInt64 offset)
{
NazaraLock(m_mutex)
NazaraAssert(IsOpen(), "File is not opened");
NazaraAssert(IsOpen(), "File is not open");
return m_impl->SetCursorPos(CursorPosition_AtBegin, offset);
}
/*!
* \brief Sets the file path
* \return true if file opening is successful
*
* \remark Produces a NazaraError if file path can not be open
*/
bool File::SetFile(const String& filePath)
{
NazaraLock(m_mutex)
@@ -285,6 +453,13 @@ namespace Nz
return true;
}
/*!
* \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);
@@ -292,6 +467,13 @@ namespace Nz
return *this;
}
/*!
* \brief Moves the other file into this
* \return A reference to this
*
* \param file File to move in this
*/
File& File::operator=(File&& file) noexcept
{
NazaraLock(m_mutex)
@@ -302,9 +484,18 @@ namespace Nz
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)
{
// Je n'utilise pas les fonctions de l'OS car elles ne fonctionnent que pour un chemin existant
// We don't use OS functions because they only work for existing path
String path = NormalizePath(filePath);
if (path.IsEmpty())
return String();
@@ -319,7 +510,7 @@ namespace Nz
base = "\\\\";
start = 2;
}
else if (path.StartsWith('\\')) // Spécial : '\' fait référence au disque racine
else if (path.StartsWith('\\')) // Special : '\' refering to root
{
String drive = Directory::GetCurrent().SubStringTo('\\');
String end = path.SubString(1, -1);
@@ -351,14 +542,14 @@ namespace Nz
if (path.Split(sep, NAZARA_DIRECTORY_SEPARATOR) <= 1)
return path;
// Nous avons un chemin absolu, mais il nous faut un peu le nettoyer
// 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) // Si nous ne sommes pas dans la partie protégée
if (i > start) // If we are not in the protected area
sep.erase(sep.begin() + i--);
sep.erase(sep.begin() + i--);
@@ -377,6 +568,14 @@ namespace Nz
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())
@@ -385,6 +584,13 @@ namespace Nz
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())
@@ -393,6 +599,13 @@ namespace Nz
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())
@@ -401,6 +614,13 @@ namespace Nz
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())
@@ -409,10 +629,23 @@ namespace Nz
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)
{
@@ -422,6 +655,13 @@ namespace Nz
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())
@@ -430,6 +670,13 @@ namespace Nz
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())
@@ -438,6 +685,13 @@ namespace Nz
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());
@@ -451,7 +705,7 @@ namespace Nz
return true;
else if (path.Match("\\\\*")) // Ex: \\Laptop
return true;
else if (path.StartsWith('\\')) // Spécial : '\' fait référence au disque racine
else if (path.StartsWith('\\')) // Special : '\' refering to the root
return true;
else
return false;
@@ -462,6 +716,13 @@ namespace Nz
#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());
@@ -475,6 +736,13 @@ namespace Nz
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);
@@ -490,6 +758,14 @@ namespace Nz
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())
@@ -498,6 +774,12 @@ namespace Nz
return FileImpl::Rename(NormalizePath(sourcePath), NormalizePath(targetPath));
}
/*!
* \brief Flushes the stream
*
* \remark Produces a NazaraAssert if file is not open
*/
void File::FlushStream()
{
NazaraLock(m_mutex)
@@ -507,11 +789,21 @@ namespace Nz
m_impl->Flush();
}
/*!
* \brief Reads blocks
* \return Number of blocks read
*
* \param buffer Preallocated buffer to contain information read
* \param size Size of the read and thus of the buffer
*
* \remark Produces a NazaraAssert if file is not open
*/
std::size_t File::ReadBlock(void* buffer, std::size_t size)
{
NazaraLock(m_mutex)
NazaraAssert(IsOpen(), "File is not opened");
NazaraAssert(IsOpen(), "File is not open");
if (size == 0)
return 0;
@@ -520,7 +812,7 @@ namespace Nz
return m_impl->Read(buffer, size);
else
{
// Si nous ne devons rien lire, nous avançons simplement
// If we don't have to read, we move forward
UInt64 currentPos = m_impl->GetCursorPos();
m_impl->SetCursorPos(CursorPosition_AtCurrent, size);
@@ -529,11 +821,22 @@ namespace Nz
}
}
/*!
* \brief Writes blocks
* \return Number of blocks written
*
* \param buffer Preallocated buffer containing information to write
* \param size Size of the writting and thus of the buffer
*
* \remark Produces a NazaraAssert if file is not open
* \remark Produces a NazaraAssert if buffer is nullptr
*/
std::size_t File::WriteBlock(const void* buffer, std::size_t size)
{
NazaraLock(m_mutex)
NazaraAssert(IsOpen(), "File is not opened");
NazaraAssert(IsOpen(), "File is not open");
if (size == 0)
return 0;
@@ -543,9 +846,22 @@ namespace Nz
return m_impl->Write(buffer, size);
}
/*!
* \brief Appends the file to the hash
* \return true if hash is successful
*
* \param hash Hash to append data of the file
* \param originalFile Path of the file
*
* \remark Produces a NazaraAssert if hash is nullptr
* \remark Produces a NazaraError if file could not be open
* \remark Produces a NazaraError if file could not be read
*/
NAZARA_CORE_API bool HashAppend(AbstractHash* hash, const File& originalFile)
{
NazaraAssert(hash, "Invalid hash");
File file(originalFile.GetPath());
if (!file.Open(OpenMode_ReadOnly))
{

View File

@@ -12,6 +12,17 @@
namespace Nz
{
/*!
* \class Nz::FileLogger
* \brief Core class that represents a file logger
*/
/*!
* \brief Constructs a FileLogger object with a file name
*
* \param logPath Path to log
*/
FileLogger::FileLogger(const String& logPath) :
m_outputFile(logPath),
m_forceStdOutput(false),
@@ -20,28 +31,64 @@ namespace Nz
{
}
/*!
* \brief Destructs the object
*/
FileLogger::~FileLogger() = default;
/*!
* \brief Enables the log of the time
*
* \param enable If true, enables the time log
*/
void FileLogger::EnableTimeLogging(bool enable)
{
m_timeLoggingEnabled = enable;
}
/*!
* \brief Enables the replication to the stdout
*
* \param enable If true, enables the replication
*/
void FileLogger::EnableStdReplication(bool enable)
{
m_stdReplicationEnabled = enable;
}
/*!
* \brief Checks whether or not the replication to the stdout is enabled
* \return true If replication is enabled
*/
bool FileLogger::IsStdReplicationEnabled()
{
return m_stdReplicationEnabled;
}
/*!
* \brief Checks whether or not the logging of the time is enabled
* \return true If logging of the time is enabled
*/
bool FileLogger::IsTimeLoggingEnabled()
{
return m_timeLoggingEnabled;
}
/*!
* \brief Writes a string in the log
*
* \param string String to log
*
* \remark Produces a NazaraError if file could not be opened
*
* \see WriteError
*/
void FileLogger::Write(const String& string)
{
if (m_forceStdOutput || m_stdReplicationEnabled)
@@ -54,8 +101,8 @@ namespace Nz
// To prevent infinite loops
m_forceStdOutput = true;
CallOnExit resetOnExit([this] ()
{
CallOnExit resetOnExit([this] ()
{
m_forceStdOutput = false;
});
@@ -85,6 +132,18 @@ namespace Nz
m_outputFile.Write(stream);
}
/*!
* \brief Writes an error in the log
*
* \param type The error type
* \param error The error text
* \param line The line the error occurred
* \param file The file the error occurred
* \param function The function the error occurred
*
* \see Write
*/
void FileLogger::WriteError(ErrorType type, const String& error, unsigned int line, const char* file, const char* function)
{
if (m_forceStdOutput || m_stdReplicationEnabled)

View File

@@ -16,13 +16,36 @@
namespace Nz
{
/*!
* \class Nz::GuillotineBinPack
* \brief Core class that represents the "Guillotine problem", combination of the "Bin packing problem" and the "cutting stock"
*/
namespace
{
/*!
* \brief Gets the score for fitting the area
* \return Score of the fitting
*
* \param width Width
* \param height Height
* \param freeRectSize Free area
*/
int ScoreBestAreaFit(int width, int height, const Rectui& freeRectSize)
{
return freeRectSize.width * freeRectSize.height - width * height;
}
/*!
* \brief Gets the score for fitting the area following long side
* \return Score of the fitting following long side
*
* \param width Width
* \param height Height
* \param freeRectSize Free area
*/
int ScoreBestLongSideFit(int width, int height, const Rectui& freeRectSize)
{
int leftoverHoriz = std::abs(static_cast<int>(freeRectSize.width - width));
@@ -32,6 +55,15 @@ namespace Nz
return leftover;
}
/*!
* \brief Gets the score for fitting the area following short side
* \return Score of the fitting following short side
*
* \param width Width
* \param height Height
* \param freeRectSize Free area
*/
int ScoreBestShortSideFit(int width, int height, const Rectui& freeRectSize)
{
int leftoverHoriz = std::abs(static_cast<int>(freeRectSize.width - width));
@@ -41,37 +73,85 @@ namespace Nz
return leftover;
}
/*!
* \brief Gets the worst score for fitting the area
* \return Worst score of the fitting
*
* \param width Width
* \param height Height
* \param freeRectSize Free area
*/
int ScoreWorstAreaFit(int width, int height, const Rectui& freeRectSize)
{
return -ScoreBestAreaFit(width, height, freeRectSize);
}
/*!
* \brief Gets the worst score for fitting the area following long side
* \return Worst score of the fitting following long side
*
* \param width Width
* \param height Height
* \param freeRectSize Free area
*/
int ScoreWorstLongSideFit(int width, int height, const Rectui& freeRectSize)
{
return -ScoreBestLongSideFit(width, height, freeRectSize);
}
/*!
* \brief Gets the worst score for fitting the area following short side
* \return Worst score of the fitting following short side
*
* \param width Width
* \param height Height
* \param freeRectSize Free area
*/
int ScoreWorstShortSideFit(int width, int height, const Rectui& freeRectSize)
{
return -ScoreBestShortSideFit(width, height, freeRectSize);
}
}
/*!
* \brief Constructs a GuillotineBinPack object by default
*/
GuillotineBinPack::GuillotineBinPack()
{
Reset();
}
/*!
* \brief Constructs a GuillotineBinPack object with width and height
*
* \param width Width
* \param height Height
*/
GuillotineBinPack::GuillotineBinPack(unsigned int width, unsigned int height)
{
Reset(width, height);
}
/*!
* \brief Constructs a GuillotineBinPack object with area
*
* \param size Vector2 representing the area (width, height)
*/
GuillotineBinPack::GuillotineBinPack(const Vector2ui& size)
{
Reset(size);
}
/*!
* \brief Clears the content
*/
void GuillotineBinPack::Clear()
{
m_freeRectangles.clear();
@@ -80,6 +160,15 @@ namespace Nz
m_usedArea = 0;
}
/*!
* \brief Expands the content
*
* \param newWidth New width for the expansion
* \param newHeight New height for the expansion
*
* \see Expand
*/
void GuillotineBinPack::Expand(unsigned int newWidth, unsigned newHeight)
{
unsigned int oldWidth = m_width;
@@ -98,52 +187,123 @@ namespace Nz
while (MergeFreeRectangles());
}
/*!
* \brief Expands the content
*
* \param newSize New area for the expansion
*
* \see Expand
*/
void GuillotineBinPack::Expand(const Vector2ui& newSize)
{
Expand(newSize.x, newSize.y);
}
/*!
* \brief Frees the rectangle
*
* \param rect Area to free
*
* \remark This method should only be called with computed rectangles by the method Insert and can produce fragmentation
*/
void GuillotineBinPack::FreeRectangle(const Rectui& rect)
{
///DOC: Cette méthode ne devrait recevoir que des rectangles calculés par la méthode Insert et peut provoquer de la fragmentation
m_freeRectangles.push_back(rect);
m_usedArea -= rect.width * rect.height;
}
/*!
* \brief Gets the height
* \return Height of the area
*/
unsigned int GuillotineBinPack::GetHeight() const
{
return m_height;
}
/*!
* \brief Gets percentage of occupation
* \return Percentage of the already occupied area
*/
float GuillotineBinPack::GetOccupancy() const
{
return static_cast<float>(m_usedArea)/(m_width*m_height);
}
/*!
* \brief Gets the size of the area
* \return Size of the area
*/
Vector2ui GuillotineBinPack::GetSize() const
{
return Vector2ui(m_width, m_height);
}
/*!
* \brief Gets the width
* \return Width of the area
*/
unsigned int GuillotineBinPack::GetWidth() const
{
return m_width;
}
/*!
* \brief Inserts rectangles in the area
* \return true if each rectangle could be inserted
*
* \param rects List of rectangles
* \param count Count of rectangles
* \param merge Merge possible
* \param rectChoice Heuristic to use to free
* \param splitMethod Heuristic to use to split
*/
bool GuillotineBinPack::Insert(Rectui* rects, unsigned int count, bool merge, FreeRectChoiceHeuristic rectChoice, GuillotineSplitHeuristic splitMethod)
{
return Insert(rects, nullptr, nullptr, count, merge, rectChoice, splitMethod);
}
/*!
* \brief Inserts rectangles in the area
* \return true if each rectangle could be inserted
*
* \param rects List of rectangles
* \param flipped List of flipped rectangles
* \param count Count of rectangles
* \param merge Merge possible
* \param rectChoice Heuristic to use to free
* \param splitMethod Heuristic to use to split
*/
bool GuillotineBinPack::Insert(Rectui* rects, bool* flipped, unsigned int count, bool merge, FreeRectChoiceHeuristic rectChoice, GuillotineSplitHeuristic splitMethod)
{
return Insert(rects, flipped, nullptr, count, merge, rectChoice, splitMethod);
}
/*!
* \brief Inserts rectangles in the area
* \return true if each rectangle could be inserted
*
* \param rects List of rectangles
* \param flipped List of flipped rectangles
* \param flipped List of inserted rectangles
* \param count Count of rectangles
* \param merge Merge possible
* \param rectChoice Heuristic to use to free
* \param splitMethod Heuristic to use to split
*/
bool GuillotineBinPack::Insert(Rectui* rects, bool* flipped, bool* inserted, unsigned int count, bool merge, FreeRectChoiceHeuristic rectChoice, GuillotineSplitHeuristic splitMethod)
{
std::vector<Rectui*> remainingRects(count); // La position du rectangle
std::vector<Rectui*> remainingRects(count); // Position of the rectangle
for (unsigned int i = 0; i < count; ++i)
remainingRects[i] = &rects[i];
@@ -214,7 +374,7 @@ namespace Nz
// If we didn't manage to find any rectangle to pack, abort.
if (bestScore == std::numeric_limits<int>::max())
{
// Si nous le pouvons, on marque les rectangles n'ayant pas pu être insérés
// If we can do it, we mark the rectangle could be inserted
if (inserted)
{
for (Rectui* rect : remainingRects)
@@ -259,9 +419,13 @@ namespace Nz
return true;
}
/*!
* \brief Merges free rectangles together
* \return true if there was a merge (and thus if a merge is still possible)
*/
bool GuillotineBinPack::MergeFreeRectangles()
{
///DOC: Renvoie true s'il y a eu fusion (et donc si une fusion est encore possible)
std::size_t oriSize = m_freeRectangles.size();
// Do a Theta(n^2) loop to see if any pair of free rectangles could me merged into one.
@@ -312,6 +476,10 @@ namespace Nz
return m_freeRectangles.size() < oriSize;
}
/*!
* \brief Resets the area
*/
void GuillotineBinPack::Reset()
{
m_height = 0;
@@ -320,6 +488,13 @@ namespace Nz
Clear();
}
/*!
* \brief Resets the area
*
* \param width Width
* \param height Height
*/
void GuillotineBinPack::Reset(unsigned int width, unsigned int height)
{
m_height = height;
@@ -328,11 +503,25 @@ namespace Nz
Clear();
}
/*!
* \brief Resets the area
*
* \param size Size of the area
*/
void GuillotineBinPack::Reset(const Vector2ui& size)
{
Reset(size.x, size.y);
}
/*!
* \brief Splits the free rectangle along axis
*
* \param freeRect Free rectangle to split
* \param placedRect Already placed rectangle
* \param splitHorizontal Split horizontally (or vertically)
*/
void GuillotineBinPack::SplitFreeRectAlongAxis(const Rectui& freeRect, const Rectui& placedRect, bool splitHorizontal)
{
// Form the two new rectangles.
@@ -365,50 +554,60 @@ namespace Nz
m_freeRectangles.push_back(right);
}
/*!
* \brief Splits the free rectangle using the heuristic
*
* \param freeRect Free rectangle to split
* \param placedRect Already placed rectangle
* \param method Method used to split
*
* \remark Produces a NazaraError if enumeration GuillotineSplitHeuristic is invalid
*/
void GuillotineBinPack::SplitFreeRectByHeuristic(const Rectui& freeRect, const Rectui& placedRect, GuillotineSplitHeuristic method)
{
// Compute the lengths of the leftover area.
// Compute the lengths of the leftover area
const int w = freeRect.width - placedRect.width;
const int h = freeRect.height - placedRect.height;
// Placing placedRect into freeRect results in an L-shaped free area, which must be split into
// two disjoint rectangles. This can be achieved with by splitting the L-shape using a single line.
// We have two choices: horizontal or vertical.
// two disjoint rectangles. This can be achieved with by splitting the L-shape using a single line
// We have two choices: horizontal or vertical
// Use the given heuristic to decide which choice to make.
// Use the given heuristic to decide which choice to make
bool splitHorizontal;
switch (method)
{
case SplitLongerAxis:
// Split along the longer total axis.
// Split along the longer total axis
splitHorizontal = (freeRect.width > freeRect.height);
break;
case SplitLongerLeftoverAxis:
// Split along the longer leftover axis.
// Split along the longer leftover axis
splitHorizontal = (w > h);
break;
case SplitMaximizeArea:
// Maximize the smaller area == minimize the larger area.
// Tries to make the rectangles more even-sized.
// Maximize the smaller area == minimize the larger area
// Tries to make the rectangles more even-sized
splitHorizontal = (placedRect.width * h <= w * placedRect.height);
break;
case SplitMinimizeArea:
// Maximize the larger area == minimize the smaller area.
// Tries to make the single bigger rectangle.
// Maximize the larger area == minimize the smaller area
// Tries to make the single bigger rectangle
splitHorizontal = (placedRect.width * h > w * placedRect.height);
break;
case SplitShorterAxis:
// Split along the shorter total axis.
// Split along the shorter total axis
splitHorizontal = (freeRect.width <= freeRect.height);
break;
case SplitShorterLeftoverAxis:
// Split along the shorter leftover axis.
// Split along the shorter leftover axis
splitHorizontal = (w <= h);
break;
@@ -417,10 +616,22 @@ namespace Nz
splitHorizontal = true;
}
// Perform the actual split.
// Perform the actual split
SplitFreeRectAlongAxis(freeRect, placedRect, splitHorizontal);
}
/*!
* \brief Gets the score using heuristic
* \return Score of the heuristic
*
* \param width Width
* \param height Height
* \param freeRect Free area
* \param rectChoice Heuristic to get score
*
* \remark Produces a NazaraError if enumeration FreeRectChoiceHeuristic is invalid
*/
int GuillotineBinPack::ScoreByHeuristic(int width, int height, const Rectui& freeRect, FreeRectChoiceHeuristic rectChoice)
{
switch (rectChoice)

View File

@@ -82,11 +82,31 @@ namespace Nz
char s_brandString[48] = "Not initialized";
}
/*!
* \class Nz::HardwareInfo
* \brief Core class that represents the info we can get from hardware
*/
/*!
* \brief Generates the cpuid instruction (available on x86 & x64)
*
* \param functionId Information to retrieve
* \param subFunctionId Additional code for information retrieval
* \param result Supported features of the CPU
*/
void HardwareInfo::Cpuid(UInt32 functionId, UInt32 subFunctionId, UInt32 result[4])
{
return HardwareInfoImpl::Cpuid(functionId, subFunctionId, result);
}
/*!
* \brief Gets the brand of the processor
* \return String of the brand
*
* \remark Produces a NazaraError if not Initialize
*/
String HardwareInfo::GetProcessorBrandString()
{
if (!Initialize())
@@ -95,13 +115,26 @@ namespace Nz
return s_brandString;
}
/*!
* \brief Gets the number of threads
* \return Number of threads available on the CPU
*
* \remark Doesn't need the initialization of HardwareInfo
*/
unsigned int HardwareInfo::GetProcessorCount()
{
///DOC: Ne nécessite pas l'initialisation de HardwareInfo pour fonctionner
static unsigned int processorCount = std::max(HardwareInfoImpl::GetProcessorCount(), 1U);
return processorCount;
}
/*!
* \brief Gets the processor vendor
* \return ProcessorVendor containing information the vendor
*
* \remark Produces a NazaraError if not Initialize
*/
ProcessorVendor HardwareInfo::GetProcessorVendor()
{
if (!Initialize())
@@ -110,6 +143,13 @@ namespace Nz
return s_vendorEnum;
}
/*!
* \brief Gets the vendor of the processor
* \return String of the vendor
*
* \remark Produces a NazaraError if not Initialize
*/
String HardwareInfo::GetProcessorVendorName()
{
if (!Initialize())
@@ -118,13 +158,26 @@ namespace Nz
return vendorNames[s_vendorEnum+1];
}
/*!
* \brief Gets the amount of total memory
* \return Number of total memory available
*
* \remark Doesn't need the initialization of HardwareInfo
*/
UInt64 HardwareInfo::GetTotalMemory()
{
///DOC: Ne nécessite pas l'initialisation de HardwareInfo pour fonctionner
static UInt64 totalMemory = HardwareInfoImpl::GetTotalMemory();
return totalMemory;
}
/*!
* \brief Checks whether the processor owns the capacity to handle certain instructions
* \return true If instructions supported
*
* \remark Produces a NazaraError if capability is a wrong enum with NAZARA_DEBUG defined
*/
bool HardwareInfo::HasCapability(ProcessorCap capability)
{
#ifdef NAZARA_DEBUG
@@ -138,9 +191,16 @@ namespace Nz
return s_capabilities[capability];
}
/*!
* \brief Initializes the HardwareInfo class
* \return true if successful
*
* \remark Produces a NazaraError if cpuid is not supported
*/
bool HardwareInfo::Initialize()
{
if (s_initialized)
if (IsInitialized())
return true;
if (!HardwareInfoImpl::IsCpuidSupported())
@@ -151,21 +211,21 @@ namespace Nz
s_initialized = true;
UInt32 registers[4]; // Récupère les quatre registres (EAX, EBX, ECX et EDX)
UInt32 registers[4]; // Get the four registers (EAX, EBX, ECX et EDX)
// Pour plus de clar
// To make it more clear
UInt32& eax = registers[0];
UInt32& ebx = registers[1];
UInt32& ecx = registers[2];
UInt32& edx = registers[3];
// Pour commencer, on va récupérer l'identifiant du constructeur ainsi que l'id de fonction maximal supporté par le CPUID
// To begin, we get the id of the constructor and the id of maximal functions supported by the CPUID
HardwareInfoImpl::Cpuid(0, 0, registers);
// Attention à l'ordre : EBX, EDX, ECX
// Watchout to the order : EBX, EDX, ECX
UInt32 manufacturerId[3] = {ebx, edx, ecx};
// Identification du concepteur
// Identification of conceptor
s_vendorEnum = ProcessorVendor_Unknown;
for (const VendorString& vendorString : vendorStrings)
{
@@ -178,7 +238,7 @@ namespace Nz
if (eax >= 1)
{
// Récupération de certaines capacités du processeur (ECX et EDX, fonction 1)
// Recuperation of certain capacities of the processor (ECX et EDX, function 1)
HardwareInfoImpl::Cpuid(1, 0, registers);
s_capabilities[ProcessorCap_AVX] = (ecx & (1U << 28)) != 0;
@@ -192,53 +252,67 @@ namespace Nz
s_capabilities[ProcessorCap_SSE42] = (ecx & (1U << 20)) != 0;
}
// Récupération de la plus grande fonction étendue supportée (EAX, fonction 0x80000000)
// Recuperation of biggest extended function handled (EAX, fonction 0x80000000)
HardwareInfoImpl::Cpuid(0x80000000, 0, registers);
UInt32 maxSupportedExtendedFunction = eax;
if (maxSupportedExtendedFunction >= 0x80000001)
{
// Récupération des capacités étendues du processeur (ECX et EDX, fonction 0x80000001)
// Recuperation of extended capabilities of the processor (ECX et EDX, fonction 0x80000001)
HardwareInfoImpl::Cpuid(0x80000001, 0, registers);
s_capabilities[ProcessorCap_x64] = (edx & (1U << 29)) != 0; // Support du 64bits, indépendant de l'OS
s_capabilities[ProcessorCap_x64] = (edx & (1U << 29)) != 0; // Support of 64bits, independant of the OS
s_capabilities[ProcessorCap_FMA4] = (ecx & (1U << 16)) != 0;
s_capabilities[ProcessorCap_SSE4a] = (ecx & (1U << 6)) != 0;
s_capabilities[ProcessorCap_XOP] = (ecx & (1U << 11)) != 0;
if (maxSupportedExtendedFunction >= 0x80000004)
{
// Récupération d'une chaîne de caractère décrivant le processeur (EAX, EBX, ECX et EDX,
// fonctions de 0x80000002 à 0x80000004 compris)
// Recuperation of the string describing the processor (EAX, EBX, ECX et EDX,
// functions from 0x80000002 to 0x80000004 inclusive)
char* ptr = &s_brandString[0];
for (UInt32 code = 0x80000002; code <= 0x80000004; ++code)
{
HardwareInfoImpl::Cpuid(code, 0, registers);
std::memcpy(ptr, &registers[0], 4*sizeof(UInt32)); // On rajoute les 16 octets à la chaîne
std::memcpy(ptr, &registers[0], 4*sizeof(UInt32)); // We add the 16 bytes to the string
ptr += 4*sizeof(UInt32);
}
// Le caractère nul faisant partie de la chaîne retournée par le CPUID, pas besoin de le rajouter
// The character '\0' is already returned
}
}
return true;
}
/*!
* \brief Checks whether the instruction of cpuid is supported
* \return true if it the case
*/
bool HardwareInfo::IsCpuidSupported()
{
return HardwareInfoImpl::IsCpuidSupported();
}
/*!
* \brief Checks whether the class HardwareInfo is initialized
* \return true if it is initialized
*/
bool HardwareInfo::IsInitialized()
{
return s_initialized;
}
/*!
* \brief Unitializes the class HardwareInfo
*/
void HardwareInfo::Uninitialize()
{
// Rien à faire
// Nothing to do
s_initialized = false;
}
}

View File

@@ -8,12 +8,27 @@
namespace Nz
{
/*!
* \class Nz::LockGuard
* \brief Core class that represents a mutex wrapper that provides a convenient RAII-style mechanism
*/
/*!
* \brief Constructs a LockGuard object with a mutex
*
* \param mutex Mutex to lock
*/
LockGuard::LockGuard(Mutex& mutex) :
m_mutex(mutex)
{
m_mutex.Lock();
}
/*!
* \brief Destructs a LockGuard object and unlocks the mutex
*/
LockGuard::~LockGuard()
{
m_mutex.Unlock();

View File

@@ -15,21 +15,48 @@ namespace Nz
StdLogger s_stdLogger;
}
/*!
* \class Nz::Log
* \brief Core class that represents a logger
*/
/*!
* \brief Enables the log
*
* \param enable If true, enables the log
*/
void Log::Enable(bool enable)
{
s_enabled = enable;
}
/*!
* \brief Gets the logger
* \return An abstract pointer to the logger
*/
AbstractLogger* Log::GetLogger()
{
return s_logger;
}
/*!
* \brief Checks whether or not the logging is enabled
* \return true If logging is enabled
*/
bool Log::IsEnabled()
{
return s_enabled;
}
/*!
* \brief Sets the logger
*
* \param logger AbstractLogger to log
*/
void Log::SetLogger(AbstractLogger* logger)
{
if (s_logger != &s_stdLogger)
@@ -40,28 +67,57 @@ namespace Nz
s_logger = &s_stdLogger;
}
/*!
* \brief Writes a string in the log
*
* \param string String to log
*
* \see WriteError
*/
void Log::Write(const String& string)
{
if (s_enabled)
s_logger->Write(string);
OnLogWrite(string);
}
/*!
* \brief Writes the error in the log
*
* \param type Type of the error
* \param error Message of the error
* \param line Line of the error
* \param file File of the error
* \param function Function of the error
*
* \see Write
*/
void Log::WriteError(ErrorType type, const String& error, unsigned int line, const char* file, const char* function)
{
if (s_enabled)
s_logger->WriteError(type, error, line, file, function);
OnLogWriteError(type, error, line, file, function);
}
/*!
* \brief Initializes the Log class
* \return true if successful
*/
bool Log::Initialize()
{
SetLogger(new FileLogger());
return true;
}
/*!
* \brief Unitializes the Log class
*/
void Log::Uninitialize()
{
SetLogger(nullptr);

View File

@@ -15,7 +15,7 @@
#include <pthread.h>
#endif
// Le seul fichier n'ayant pas à inclure Debug.hpp
// The only file that does not need to include Debug.hpp
namespace Nz
{
@@ -61,18 +61,43 @@ namespace Nz
CRITICAL_SECTION s_mutex;
#elif defined(NAZARA_PLATFORM_POSIX)
pthread_mutex_t s_mutex = PTHREAD_MUTEX_INITIALIZER;
#else
#error Lack of implementation: Mutex
#endif
}
/*!
* \class Nz::MemoryManager
* \brief Core class that represents a manager for the memory
*/
/*!
* \brief Constructs a MemoryManager object by default
*/
MemoryManager::MemoryManager()
{
}
/*!
* \brief Destructs a MemoryManager object and calls Unitialize
*/
MemoryManager::~MemoryManager()
{
Uninitialize();
}
/*!
* \brief Allocates memory
* \return Raw memory allocated
*
* \param size Size to allocate
* \parma multi Array or not
* \param file File of the allocation
* \param line Line of the allocation in the file
*/
void* MemoryManager::Allocate(std::size_t size, bool multi, const char* file, unsigned int line)
{
if (!s_initialized)
@@ -147,16 +172,37 @@ namespace Nz
return reinterpret_cast<UInt8*>(ptr) + sizeof(Block);
}
/*!
* \brief Enables the filling of the allocation
*
* \param allocationFilling If true, sets the rest of the allocation block to '0xFF'
*/
void MemoryManager::EnableAllocationFilling(bool allocationFilling)
{
s_allocationFilling = allocationFilling;
}
/*!
* \brief Enables the logging of the allocation
*
* \param logAllocations If true, registers every allocation
*/
void MemoryManager::EnableAllocationLogging(bool logAllocations)
{
s_allocationLogging = logAllocations;
}
/*!
* \brief Frees the pointer
*
* \param pointer Pointer to free
* \param multi Array or not
*
* \remark If pointer is nullptr, nothing is done
*/
void MemoryManager::Free(void* pointer, bool multi)
{
if (!pointer)
@@ -227,37 +273,73 @@ namespace Nz
#endif
}
/*!
* \brief Gets the number of allocated blocks
* \return Number of allocated blocks
*/
unsigned int MemoryManager::GetAllocatedBlockCount()
{
return s_allocatedBlock;
}
/*!
* \brief Gets the allocated size
* \return Size of total allocation
*/
std::size_t MemoryManager::GetAllocatedSize()
{
return s_allocatedSize;
}
/*!
* \brief Gets the number of allocations
* \return Number of allocations
*/
unsigned int MemoryManager::GetAllocationCount()
{
return s_allocationCount;
}
/*!
* \brief Checks whether the filling of allocation is enabled
* \return true if it is filling
*/
bool MemoryManager::IsAllocationFillingEnabled()
{
return s_allocationFilling;
}
/*!
* \brief Checks whether the logging of allocation is enabled
* \return true if it is logging
*/
bool MemoryManager::IsAllocationLoggingEnabled()
{
return s_allocationLogging;
}
/*!
* \brief Sets the next free
*
* \param file Name of the file
* \param line Line in the file
*/
void MemoryManager::NextFree(const char* file, unsigned int line)
{
s_nextFreeFile = file;
s_nextFreeLine = line;
}
/*!
* \brief Initializes the MemoryManager
*/
void MemoryManager::Initialize()
{
char timeStr[23];
@@ -282,12 +364,22 @@ namespace Nz
s_initialized = true;
}
/*!
* \brief Gets the time
*
* \param buffer Buffer to set the time in
*/
void MemoryManager::TimeInfo(char buffer[23])
{
time_t currentTime = std::time(nullptr);
std::strftime(buffer, 23, "%d/%m/%Y - %H:%M:%S:", std::localtime(&currentTime));
}
/*!
* \brief Uninitializes the MemoryManager
*/
void MemoryManager::Uninitialize()
{
#ifdef NAZARA_PLATFORM_WINDOWS
@@ -334,5 +426,5 @@ namespace Nz
}
std::fclose(log);
}
}
}

View File

@@ -10,33 +10,75 @@
namespace Nz
{
/*!
* \class Nz::MemoryStream
* \brief Core class that represents a stream of memory
*/
/*!
* \brief Clears the content of the stream
*/
void MemoryStream::Clear()
{
m_buffer->Clear();
m_pos = 0;
}
/*!
* \brief Checks whether the stream reached the end of the stream
* \return true if cursor is at the end of the stream
*/
bool MemoryStream::EndOfStream() const
{
return m_pos >= m_buffer->size();
}
/*!
* \brief Gets the position of the cursor
* \return Position of the cursor
*/
UInt64 MemoryStream::GetCursorPos() const
{
return m_pos;
}
/*!
* \brief Gets the size of the raw memory
* \return Size of the memory
*/
UInt64 MemoryStream::GetSize() const
{
return m_buffer->GetSize();
}
/*!
* \brief Sets the buffer for the memory stream
*
* \param byteArray Bytes to stream
* \param openMode Reading/writing mode for the stream
*
* \remark Produces a NazaraAssert if byteArray is nullptr
*/
void MemoryStream::SetBuffer(ByteArray* byteArray, UInt32 openMode)
{
NazaraAssert(byteArray, "Invalid ByteArray");
m_buffer = byteArray;
m_openMode = openMode;
}
/*!
* \brief Sets the position of the cursor
* \return true
*
* \param offset Offset according to the beginning of the stream
*/
bool MemoryStream::SetCursorPos(UInt64 offset)
{
m_pos = offset;
@@ -44,11 +86,23 @@ namespace Nz
return true;
}
/*!
* \brief Flushes the stream
*/
void MemoryStream::FlushStream()
{
// Nothing to flush
}
/*!
* \brief Reads blocks
* \return Number of blocks read
*
* \param buffer Preallocated buffer to contain information read
* \param size Size of the read and thus of the buffer
*/
std::size_t MemoryStream::ReadBlock(void* buffer, std::size_t size)
{
if (EndOfStream())
@@ -63,14 +117,26 @@ namespace Nz
return readSize;
}
/*!
* \brief Writes blocks
* \return Number of blocks written
*
* \param buffer Preallocated buffer containing information to write
* \param size Size of the writting and thus of the buffer
*
* \remark Produces a NazaraAssert if buffer is nullptr
*/
std::size_t MemoryStream::WriteBlock(const void* buffer, std::size_t size)
{
std::size_t endPos = static_cast<std::size_t>(m_pos + size);
if (endPos > m_buffer->GetSize())
m_buffer->Resize(endPos);
NazaraAssert(buffer, "Invalid buffer");
std::memcpy(m_buffer->GetBuffer() + m_pos, buffer, size);
m_pos = endPos;
return size;
}

View File

@@ -9,6 +9,20 @@
namespace Nz
{
/*!
* \class Nz::MemoryView
* \brief Core class that represents a view of the memory behaving like a stream
*/
/*!
* \brief Constructs a MemoryView object with a raw memory and a size
*
* \param ptr Pointer to raw memory
* \param size Size that can be read
*
* \remark If preallocated space of ptr is less than the size, the behaviour is undefined
*/
MemoryView::MemoryView(void* ptr, UInt64 size) :
Stream(StreamOption_None, OpenMode_ReadWrite),
m_ptr(reinterpret_cast<UInt8*>(ptr)),
@@ -17,6 +31,15 @@ namespace Nz
{
}
/*!
* \brief Constructs a MemoryView object with a raw memory and a size
*
* \param ptr Constant pointer to raw memory
* \param size Size that can be read
*
* \remark If preallocated space of ptr is less than the size, the behaviour is undefined
*/
MemoryView::MemoryView(const void* ptr, UInt64 size) :
Stream(StreamOption_None, OpenMode_ReadOnly),
m_ptr(reinterpret_cast<UInt8*>(const_cast<void*>(ptr))), //< Okay, right, const_cast is bad, but this pointer is still read-only
@@ -25,21 +48,43 @@ namespace Nz
{
}
/*!
* \brief Checks whether the stream reached the end of the stream
* \return true if cursor is at the end of the stream
*/
bool MemoryView::EndOfStream() const
{
return m_pos >= m_size;
}
/*!
* \brief Gets the position of the cursor
* \return Position of the cursor
*/
UInt64 MemoryView::GetCursorPos() const
{
return m_pos;
}
/*!
* \brief Gets the size of the raw memory
* \return Size of the memory
*/
UInt64 MemoryView::GetSize() const
{
return m_size;
}
/*!
* \brief Sets the position of the cursor
* \return true
*
* \param offset Offset according to the beginning of the stream
*/
bool MemoryView::SetCursorPos(UInt64 offset)
{
m_pos = std::min(offset, m_size);
@@ -47,11 +92,23 @@ namespace Nz
return true;
}
/*!
* \brief Flushes the stream
*/
void MemoryView::FlushStream()
{
// Nothing to do
}
/*!
* \brief Reads blocks
* \return Number of blocks read
*
* \param buffer Preallocated buffer to contain information read
* \param size Size of the read and thus of the buffer
*/
std::size_t MemoryView::ReadBlock(void* buffer, std::size_t size)
{
std::size_t readSize = std::min<std::size_t>(size, static_cast<std::size_t>(m_size - m_pos));
@@ -63,12 +120,24 @@ namespace Nz
return readSize;
}
/*!
* \brief Writes blocks
* \return Number of blocks written
*
* \param buffer Preallocated buffer containing information to write
* \param size Size of the writting and thus of the buffer
*
* \remark Produces a NazaraAssert if buffer is nullptr
*/
std::size_t MemoryView::WriteBlock(const void* buffer, std::size_t size)
{
std::size_t endPos = static_cast<std::size_t>(m_pos + size);
if (endPos > m_size)
size = m_size - m_pos;
NazaraAssert(buffer, "Invalid buffer");
std::memcpy(&m_ptr[m_pos], buffer, size);
m_pos += size;

View File

@@ -16,26 +16,58 @@
namespace Nz
{
/*!
* \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()
{
m_impl->Lock();
}
/*!
* \brief Tries to lock the mutex
* \return true if the lock was acquired successfully
*/
bool Mutex::TryLock()
{
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()
{
m_impl->Unlock();

View File

@@ -12,16 +12,33 @@
namespace Nz
{
/*!
* \class Nz::ParameterList
* \brief Core class that represents a list of parameters
*/
/*!
* \brief Constructs a ParameterList object by copy
*/
ParameterList::ParameterList(const ParameterList& list)
{
operator=(list);
}
/*!
* \brief Destructs the object and clears
*/
ParameterList::~ParameterList()
{
Clear();
}
/*!
* \brief Clears the list of parameters
*/
void ParameterList::Clear()
{
for (auto it = m_parameters.begin(); it != m_parameters.end(); ++it)
@@ -30,8 +47,22 @@ namespace Nz
m_parameters.clear();
}
/*!
* \brief Gets the boolean parameter by name
* \return true if success
*
* \param name Name of the variable
* \param value Value to set
*
* \remark Produces a NazaraAssert if pointer is invalid
* \remark Produces a NazaraError if name is not a variable
* \remark Produces a NazaraError if value could not be convertible
*/
bool ParameterList::GetBooleanParameter(const String& name, bool* value) const
{
NazaraAssert(value, "Invalid pointer");
auto it = m_parameters.find(name);
if (it == m_parameters.end())
{
@@ -50,16 +81,16 @@ namespace Nz
return true;
case ParameterType_String:
{
bool converted;
if (it->second.value.stringVal.ToBool(&converted, String::CaseInsensitive))
{
*value = converted;
return true;
}
bool converted;
if (it->second.value.stringVal.ToBool(&converted, String::CaseInsensitive))
{
*value = converted;
return true;
}
break;
}
break;
}
case ParameterType_Float:
case ParameterType_None:
@@ -72,8 +103,22 @@ namespace Nz
return false;
}
/*!
* \brief Gets the float parameter by name
* \return true if success
*
* \param name Name of the variable
* \param value Value to set
*
* \remark Produces a NazaraAssert if pointer is invalid
* \remark Produces a NazaraError if name is not a variable
* \remark Produces a NazaraError if value could not be convertible
*/
bool ParameterList::GetFloatParameter(const String& name, float* value) const
{
NazaraAssert(value, "Invalid pointer");
auto it = m_parameters.find(name);
if (it == m_parameters.end())
{
@@ -92,16 +137,16 @@ namespace Nz
return true;
case ParameterType_String:
{
double converted;
if (it->second.value.stringVal.ToDouble(&converted))
{
*value = static_cast<float>(converted);
return true;
}
double converted;
if (it->second.value.stringVal.ToDouble(&converted))
{
*value = static_cast<float>(converted);
return true;
}
break;
}
break;
}
case ParameterType_Boolean:
case ParameterType_None:
@@ -114,8 +159,22 @@ namespace Nz
return false;
}
/*!
* \brief Gets the integer parameter by name
* \return true if success
*
* \param name Name of the variable
* \param value Value to set
*
* \remark Produces a NazaraAssert if pointer is invalid
* \remark Produces a NazaraError if name is not a variable
* \remark Produces a NazaraError if value could not be convertible
*/
bool ParameterList::GetIntegerParameter(const String& name, int* value) const
{
NazaraAssert(value, "Invalid pointer");
auto it = m_parameters.find(name);
if (it == m_parameters.end())
{
@@ -138,18 +197,18 @@ namespace Nz
return false;
case ParameterType_String:
{
long long converted;
if (it->second.value.stringVal.ToInteger(&converted))
{
if (converted <= std::numeric_limits<int>::max() && converted >= std::numeric_limits<int>::min())
long long converted;
if (it->second.value.stringVal.ToInteger(&converted))
{
*value = static_cast<int>(converted);
return true;
if (converted <= std::numeric_limits<int>::max() && converted >= std::numeric_limits<int>::min())
{
*value = static_cast<int>(converted);
return true;
}
}
break;
}
break;
}
case ParameterType_None:
case ParameterType_Pointer:
@@ -161,8 +220,22 @@ namespace Nz
return false;
}
/*!
* \brief Gets the parameter by name
* \return true if success
*
* \param name Name of the variable
* \param type Type to set
*
* \remark Produces a NazaraAssert if pointer is invalid
* \remark Produces a NazaraError if name is not a variable
* \remark Produces a NazaraError if value could not be convertible
*/
bool ParameterList::GetParameterType(const String& name, ParameterType* type) const
{
NazaraAssert(type, "Invalid pointer");
auto it = m_parameters.find(name);
if (it == m_parameters.end())
return false;
@@ -172,8 +245,22 @@ namespace Nz
return true;
}
/*!
* \brief Gets the pointer parameter by name
* \return true if success
*
* \param name Name of the variable
* \param value Value to set
*
* \remark Produces a NazaraAssert if pointer is invalid
* \remark Produces a NazaraError if name is not a variable
* \remark Produces a NazaraError if value could not be convertible
*/
bool ParameterList::GetPointerParameter(const String& name, void** value) const
{
NazaraAssert(value, "Invalid pointer");
auto it = m_parameters.find(name);
if (it == m_parameters.end())
{
@@ -203,8 +290,22 @@ namespace Nz
return false;
}
/*!
* \brief Gets the string parameter by name
* \return true if success
*
* \param name Name of the variable
* \param value Value to set
*
* \remark Produces a NazaraAssert if pointer is invalid
* \remark Produces a NazaraError if name is not a variable
* \remark Produces a NazaraError if value could not be convertible
*/
bool ParameterList::GetStringParameter(const String& name, String* value) const
{
NazaraAssert(value, "Invalid pointer");
auto it = m_parameters.find(name);
if (it == m_parameters.end())
{
@@ -247,8 +348,22 @@ namespace Nz
return false;
}
/*!
* \brief Gets the user parameter by name
* \return true if success
*
* \param name Name of the variable
* \param value Value to set
*
* \remark Produces a NazaraAssert if pointer is invalid
* \remark Produces a NazaraError if name is not a variable
* \remark Produces a NazaraError if value could not be convertible
*/
bool ParameterList::GetUserdataParameter(const String& name, void** value) const
{
NazaraAssert(value, "Invalid pointer");
auto it = m_parameters.find(name);
if (it == m_parameters.end())
{
@@ -268,11 +383,26 @@ namespace Nz
}
}
/*!
* \brief Checks whether the parameter list has a parameter with that name
* \return true if found
*
* \param name Name of the parameter
*/
bool ParameterList::HasParameter(const String& name) const
{
return m_parameters.find(name) != m_parameters.end();
}
/*!
* \brief Removes the parameter with that name
*
* Removes the parameter with that name, if not found, nothing is done
*
* \param name Name of the parameter
*/
void ParameterList::RemoveParameter(const String& name)
{
auto it = m_parameters.find(name);
@@ -283,6 +413,12 @@ namespace Nz
}
}
/*!
* \brief Sets the parameter with the name to ParameterType_None
*
* \param name Name of the parameter
*/
void ParameterList::SetParameter(const String& name)
{
std::pair<ParameterMap::iterator, bool> pair = m_parameters.insert(std::make_pair(name, Parameter()));
@@ -294,6 +430,13 @@ namespace Nz
parameter.type = ParameterType_None;
}
/*!
* \brief Sets the parameter with the name to the value
*
* \param name Name of the parameter
* \param value Value of the parameter
*/
void ParameterList::SetParameter(const String& name, const String& value)
{
std::pair<ParameterMap::iterator, bool> pair = m_parameters.insert(std::make_pair(name, Parameter()));
@@ -307,6 +450,13 @@ namespace Nz
PlacementNew<String>(&parameter.value.stringVal, value);
}
/*!
* \brief Sets the parameter with the name to the value
*
* \param name Name of the parameter
* \param value Value of the parameter
*/
void ParameterList::SetParameter(const String& name, const char* value)
{
std::pair<ParameterMap::iterator, bool> pair = m_parameters.insert(std::make_pair(name, Parameter()));
@@ -320,6 +470,13 @@ namespace Nz
PlacementNew<String>(&parameter.value.stringVal, value);
}
/*!
* \brief Sets the parameter with the name to the value
*
* \param name Name of the parameter
* \param value Value of the parameter
*/
void ParameterList::SetParameter(const String& name, void* value)
{
std::pair<ParameterMap::iterator, bool> pair = m_parameters.insert(std::make_pair(name, Parameter()));
@@ -332,6 +489,14 @@ namespace Nz
parameter.value.ptrVal = value;
}
/*!
* \brief Sets the parameter with the name to the value
*
* \param name Name of the parameter
* \param value Value of the parameter
* \param destructor Destructor for dynamic variable
*/
void ParameterList::SetParameter(const String& name, void* value, Destructor destructor)
{
std::pair<ParameterMap::iterator, bool> pair = m_parameters.insert(std::make_pair(name, Parameter()));
@@ -344,6 +509,13 @@ namespace Nz
parameter.value.userdataVal = new Parameter::UserdataValue(destructor, value);
}
/*!
* \brief Sets the parameter with the name to the value
*
* \param name Name of the parameter
* \param value Value of the parameter
*/
void ParameterList::SetParameter(const String& name, bool value)
{
std::pair<ParameterMap::iterator, bool> pair = m_parameters.insert(std::make_pair(name, Parameter()));
@@ -356,6 +528,13 @@ namespace Nz
parameter.value.boolVal = value;
}
/*!
* \brief Sets the parameter with the name to the value
*
* \param name Name of the parameter
* \param value Value of the parameter
*/
void ParameterList::SetParameter(const String& name, float value)
{
std::pair<ParameterMap::iterator, bool> pair = m_parameters.insert(std::make_pair(name, Parameter()));
@@ -368,6 +547,13 @@ namespace Nz
parameter.value.floatVal = value;
}
/*!
* \brief Sets the parameter with the name to the value
*
* \param name Name of the parameter
* \param value Value of the parameter
*/
void ParameterList::SetParameter(const String& name, int value)
{
std::pair<ParameterMap::iterator, bool> pair = m_parameters.insert(std::make_pair(name, Parameter()));
@@ -380,6 +566,13 @@ namespace Nz
parameter.value.intVal = value;
}
/*!
* \brief Assigns the content of the other parameter list to this
* \return A reference to this
*
* \param list List to assign
*/
ParameterList& ParameterList::operator=(const ParameterList& list)
{
Clear();
@@ -418,6 +611,12 @@ namespace Nz
return *this;
}
/*!
* \brief Destroys the value for the parameter
*
* \param parameter Parameter to destroy
*/
void ParameterList::DestroyValue(Parameter& parameter)
{
switch (parameter.type)
@@ -427,15 +626,15 @@ namespace Nz
break;
case ParameterType_Userdata:
{
Parameter::UserdataValue* userdata = parameter.value.userdataVal;
if (--userdata->counter == 0)
{
userdata->destructor(userdata->ptr);
delete userdata;
Parameter::UserdataValue* userdata = parameter.value.userdataVal;
if (--userdata->counter == 0)
{
userdata->destructor(userdata->ptr);
delete userdata;
}
break;
}
break;
}
case ParameterType_Boolean:
case ParameterType_Float:

View File

@@ -24,6 +24,19 @@ namespace Nz
};
}
/*!
* \class Nz::PluginManager
* \brief Core class that represents a manager for plugin
*/
/*!
* \brief Adds a directory
*
* \param directoryPath Path to the directory
*
* \remark Produces a NazaraError if not initialized
*/
void PluginManager::AddDirectory(const String& directoryPath)
{
if (!Initialize())
@@ -35,6 +48,11 @@ namespace Nz
s_directories.insert(File::AbsolutePath(directoryPath));
}
/*!
* \brief Initializes the plugin manager
* \return true if everything is ok
*/
bool PluginManager::Initialize()
{
if (s_initialized)
@@ -48,11 +66,36 @@ namespace Nz
return true;
}
/*!
* \brief Mounts the plugin
* \return true if mounting was a success
*
* \remark Produces a NazaraError if not initialized
* \remark Produces a NazaraError if plugin is not found
* \remark Produces a NazaraError if fail to load plugin
* \remark Produces a NazaraError if fail to get symbol PluginLoad
* \remark Produces a NazaraError if fail to initialize the plugin with PluginLoad
*/
bool PluginManager::Mount(Plugin plugin)
{
return Mount(s_pluginFiles[plugin]);
}
/*!
* \brief Mounts the plugin with a path
* \return true if mounting was a success
*
* \param pluginPath Path to the plugin
* \param appendExtension Adds the extension to the path or not
*
* \remark Produces a NazaraError if not initialized
* \remark Produces a NazaraError if plugin is not found
* \remark Produces a NazaraError if fail to load plugin
* \remark Produces a NazaraError if fail to get symbol PluginLoad
* \remark Produces a NazaraError if fail to initialize the plugin with PluginLoad
*/
bool PluginManager::Mount(const String& pluginPath, bool appendExtension)
{
if (!Initialize())
@@ -119,6 +162,14 @@ namespace Nz
return true;
}
/*!
* \brief Removes a directory
*
* \param directoryPath Path to the directory
*
* \remark Produces a NazaraError if not initialized
*/
void PluginManager::RemoveDirectory(const String& directoryPath)
{
if (!Initialize())
@@ -130,11 +181,29 @@ namespace Nz
s_directories.erase(File::AbsolutePath(directoryPath));
}
/*!
* \brief Unmounts the plugin with a path
*
* \param pluginPath Path to the plugin
*
* \remark Produces a NazaraError if not initialized
* \remark Produces a NazaraError if plugin is not loaded
*/
void PluginManager::Unmount(Plugin plugin)
{
Unmount(s_pluginFiles[plugin]);
}
/*!
* \brief Unmounts the plugin with a path
*
* \param pluginPath Path to the plugin
*
* \remark Produces a NazaraError if not initialized
* \remark Produces a NazaraError if plugin is not loaded
*/
void PluginManager::Unmount(const String& pluginPath)
{
if (!Initialize())
@@ -160,6 +229,10 @@ namespace Nz
s_plugins.erase(it);
}
/*!
* \brief Uninitializes the plugin manager
*/
void PluginManager::Uninitialize()
{
if (!s_initialized)

View File

@@ -18,8 +18,8 @@ namespace Nz
void FileImpl::Close()
{
if (m_fileDescriptor != -1)
close(m_fileDescriptor);
if (m_fileDescriptor != -1)
close(m_fileDescriptor);
}
bool FileImpl::EndOfFile() const
@@ -62,16 +62,16 @@ namespace Nz
flags = O_CREAT | O_WRONLY;
else
return false;
if (mode & OpenMode_Append)
flags |= O_APPEND;
if (mode & OpenMode_Truncate)
flags |= O_TRUNC;
///TODO: lock
// if ((mode & OpenMode_Lock) == 0)
// shareMode |= FILE_SHARE_WRITE;
///TODO: lock
//if ((mode & OpenMode_Lock) == 0)
// shareMode |= FILE_SHARE_WRITE;
m_fileDescriptor = open64(filePath.GetConstBuffer(), flags, permissions);
return m_fileDescriptor != -1;

View File

@@ -13,7 +13,7 @@ namespace Nz
{
SemaphoreImpl::SemaphoreImpl(unsigned int count)
{
if(sem_init(&m_semaphore, 0, count) != 0)
if (sem_init(&m_semaphore, 0, count) != 0)
NazaraError("Failed to create semaphore: " + Error::GetLastSystemError());
}
@@ -68,7 +68,7 @@ namespace Nz
return true;
#else
return sem_timedwait(&m_semaphore, &ti) != 0;
return sem_timedwait(&m_semaphore, &ti) != 0;
#endif
}
}

View File

@@ -8,71 +8,199 @@
namespace Nz
{
/*!
* \class Nz::PrimitiveList
* \brief Core class that represents a list of geometric primitives
*/
/*!
* \brief Adds a box centered
*
* \param lengths (Width, Height, Depht)
* \param subdivision Number of subdivision for the axis
* \param transformMatrix Matrix to apply
*/
void PrimitiveList::AddBox(const Vector3f& lengths, const Vector3ui& subdivision, const Matrix4f& transformMatrix)
{
m_primitives.push_back(Primitive::Box(lengths, subdivision, transformMatrix));
}
/*!
* \brief Adds a box centered
*
* \param lengths (Width, Height, Depht)
* \param subdivision Number of subdivision for the axis
* \param position Position of the box
* \param rotation Rotation of the box
*/
void PrimitiveList::AddBox(const Vector3f& lengths, const Vector3ui& subdivision, const Vector3f& position, const Quaternionf& rotation)
{
m_primitives.push_back(Primitive::Box(lengths, subdivision, position, rotation));
}
/*!
* \brief Adds a cone, centered in (0, 0, 0) and circle in (0, -length, 0)
*
* \param length Height of the cone
* \param radius Width of the radius
* \param subdivision Number of sides for the circle
* \param transformMatrix Matrix to apply
*/
void PrimitiveList::AddCone(float length, float radius, unsigned int subdivision, const Matrix4f& transformMatrix)
{
m_primitives.push_back(Primitive::Cone(length, radius, subdivision, transformMatrix));
}
/*!
* \brief Adds a cone, centered in (0, 0, 0) and circle in (0, -length, 0)
*
* \param length Height of the cone
* \param radius Width of the radius
* \param subdivision Number of sides for the circle
* \param position Position of the cone
* \param rotation Rotation of the cone
*/
void PrimitiveList::AddCone(float length, float radius, unsigned int subdivision, const Vector3f& position, const Quaternionf& rotation)
{
m_primitives.push_back(Primitive::Cone(length, radius, subdivision, position, rotation));
}
/*!
* \brief Adds a cubic sphere, centered in (0, 0, 0)
*
* \param size Radius of the cubic sphere
* \param subdivision Number of subdivision for the box
* \param transformMatrix Matrix to apply
*/
void PrimitiveList::AddCubicSphere(float size, unsigned int subdivision, const Matrix4f& transformMatrix)
{
m_primitives.push_back(Primitive::CubicSphere(size, subdivision, transformMatrix));
}
/*!
* \brief Adds a cubic sphere, centered in (0, 0, 0)
*
* \param size Radius of the cubic sphere
* \param subdivision Number of subdivision for the box
* \param position Position of the cubic sphere
* \param rotation Rotation of the cubic sphere
*/
void PrimitiveList::AddCubicSphere(float size, unsigned int subdivision, const Vector3f& position, const Quaternionf& rotation)
{
m_primitives.push_back(Primitive::CubicSphere(size, subdivision, position, rotation));
}
/*!
* \brief Adds a icosphere, centered in (0, 0, 0)
*
* \param size Radius of the icosphere
* \param recursionLevel Number of recursion for the icosphere
* \param transformMatrix Matrix to apply
*/
void PrimitiveList::AddIcoSphere(float size, unsigned int recursionLevel, const Matrix4f& transformMatrix)
{
m_primitives.push_back(Primitive::IcoSphere(size, recursionLevel, transformMatrix));
}
/*!
* \brief Adds a icosphere, centered in (0, 0, 0)
*
* \param size Radius of the sphere
* \param recursionLevel Number of recursion for the icosphere
* \param position Position of the icosphere
* \param rotation Rotation of the icosphere
*/
void PrimitiveList::AddIcoSphere(float size, unsigned int recursionLevel, const Vector3f& position, const Quaternionf& rotation)
{
m_primitives.push_back(Primitive::IcoSphere(size, recursionLevel, position, rotation));
}
/*!
* \brief Adds a plane, centered in (0, 0, 0)
*
* \param size (Width, Depth)
* \param subdivision Number of subdivision for the axis
* \param transformMatrix Matrix to apply
*/
void PrimitiveList::AddPlane(const Vector2f& size, const Vector2ui& subdivision, const Matrix4f& transformMatrix)
{
m_primitives.push_back(Primitive::Plane(size, subdivision, transformMatrix));
}
/*!
* \brief Adds a plane, centered in (0, 0, 0)
*
* \param size (Width, Depth)
* \param subdivision Number of subdivision for the axis
* \param planeInfo Information for the plane
*/
void PrimitiveList::AddPlane(const Vector2f& size, const Vector2ui& subdivision, const Planef& planeInfo)
{
m_primitives.push_back(Primitive::Plane(size, subdivision, planeInfo));
}
/*!
* \brief Adds a plane, centered in (0, 0, 0)
*
* \param size (Width, Depth)
* \param subdivision Number of subdivision for the axis
* \param position Position of the plane
* \param rotation Rotation of the plane
*/
void PrimitiveList::AddPlane(const Vector2f& size, const Vector2ui& subdivision, const Vector3f& position, const Quaternionf& rotation)
{
m_primitives.push_back(Primitive::Plane(size, subdivision, position, rotation));
}
/*!
* \brief Adds a UV sphere, centered in (0, 0, 0)
*
* \param size Radius of the sphere
* \param sliceCount Number of slices
* \param stackCount Number of stacks
* \param transformMatrix Matrix to apply
*/
void PrimitiveList::AddUVSphere(float size, unsigned int sliceCount, unsigned int stackCount, const Matrix4f& transformMatrix)
{
m_primitives.push_back(Primitive::UVSphere(size, sliceCount, stackCount, transformMatrix));
}
/*!
* \brief Adds a UV sphere, centered in (0, 0, 0)
*
* \param size Radius of the sphere
* \param sliceCount Number of slices
* \param stackCount Number of stacks
* \param position Position of the box
* \param rotation Rotation of the box
*/
void PrimitiveList::AddUVSphere(float size, unsigned int sliceCount, unsigned int stackCount, const Vector3f& position, const Quaternionf& rotation)
{
m_primitives.push_back(Primitive::UVSphere(size, sliceCount, stackCount, position, rotation));
}
/*!
* \brief Gets the ith primitive
* \return A reference to the ith primitive
*
* \param i Index of the primitive
*
* \remark Produces a NazaraAssert if index is greather than the size
*/
Primitive& PrimitiveList::GetPrimitive(std::size_t i)
{
NazaraAssert(i < m_primitives.size(), "Primitive index out of range");
@@ -80,6 +208,15 @@ namespace Nz
return m_primitives[i];
}
/*!
* \brief Gets the ith primitive
* \return A constant reference to the ith primitive
*
* \param i Index of the primitive
*
* \remark Produces a NazaraAssert if index is greather than the size
*/
const Primitive& PrimitiveList::GetPrimitive(std::size_t i) const
{
NazaraAssert(i < m_primitives.size(), "Primitive index out of range");
@@ -87,16 +224,39 @@ namespace Nz
return m_primitives[i];
}
/*!
* \brief Gets the number of primitives
* \return Number of primitives
*/
std::size_t PrimitiveList::GetSize() const
{
return m_primitives.size();
}
/*!
* \brief Gets the ith primitive
* \return A reference to the ith primitive
*
* \param i Index of the primitive
*
* \remark Produces a NazaraAssert if index is greather than the size
*/
Primitive& PrimitiveList::operator()(unsigned int i)
{
return GetPrimitive(i);
}
/*!
* \brief Gets the ith primitive
* \return A constant reference to the ith primitive
*
* \param i Index of the primitive
*
* \remark Produces a NazaraAssert if index is greather than the size
*/
const Primitive& PrimitiveList::operator()(unsigned int i) const
{
return GetPrimitive(i);

View File

@@ -16,12 +16,29 @@
namespace Nz
{
/*!
* \class Nz::RefCounted
* \brief Core class that represents a reference with a counter
*/
/*!
* \brief Constructs a RefCounted object with a persistance aspect
*
* \param persistent if false, object is destroyed when no more referenced
*/
RefCounted::RefCounted(bool persistent) :
m_persistent(persistent),
m_referenceCount(0)
{
}
/*!
* \brief Destructs the object
*
* \remark Produces a NazaraWarning if still referenced with NAZARA_CORE_SAFE defined
*/
RefCounted::~RefCounted()
{
#if NAZARA_CORE_SAFE
@@ -30,21 +47,42 @@ namespace Nz
#endif
}
/*!
* \brief Adds a reference to the object
*/
void RefCounted::AddReference() const
{
m_referenceCount++;
}
/*!
* \brief Gets the number of references to the object
* \return Number of references
*/
unsigned int RefCounted::GetReferenceCount() const
{
return m_referenceCount;
}
/*!
* \brief Checks whether the object is persistent
* \return true if object is not destroyed when no more referenced
*/
bool RefCounted::IsPersistent() const
{
return m_persistent;
}
/*!
* \brief Removes a reference to the object
* \return true if object is deleted because no more referenced
*
* \remark Produces a NazaraError if counter is already 0 with NAZARA_CORE_SAFE defined
*/
bool RefCounted::RemoveReference() const
{
#if NAZARA_CORE_SAFE
@@ -65,6 +103,14 @@ namespace Nz
return false;
}
/*!
* \brief Sets the persistence of the object
* \return true if object is deleted because no more referenced
*
* \param persistent Sets the persistence of the object
* \param checkReferenceCount Checks if the object should be destroyed if true
*/
bool RefCounted::SetPersistent(bool persistent, bool checkReferenceCount)
{
m_persistent = persistent;

View File

@@ -7,13 +7,29 @@
namespace Nz
{
/*!
* \class Nz::Resource
* \brief Core class that represents a resource
*/
Resource::~Resource() = default;
/*!
* \brief Gets the file path associated with the resource
* \return A reference to the path
*/
const String& Resource::GetFilePath() const
{
return m_filePath;
}
/*!
* \brief Sets the file path associated with the resource
*
* \param filePath Path to the resource
*/
void Resource::SetFilePath(const String& filePath)
{
m_filePath = filePath;

View File

@@ -16,31 +16,68 @@
namespace Nz
{
/*!
* \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

@@ -13,8 +13,8 @@ namespace Nz
const char* errorType[] = {
"Assert failed", // ErrorType_AssertFailed
"Internal error", // ErrorType_Internal
"Error", // ErrorType_Normal
"Warning" // ErrorType_Warning
"Error", // ErrorType_Normal
"Warning" // ErrorType_Warning
};
static_assert(sizeof(errorType) / sizeof(const char*) == ErrorType_Max + 1, "Error type array is incomplete");
@@ -22,15 +22,17 @@ namespace Nz
/*!
* \class Nz::StdLogger
* \brief Logger writing to standard output (stdout, stderr)
* \brief Core class that represents a logger writing to standard output (stdout, stderr)
*/
StdLogger::~StdLogger() = default;
/*!
* \brief Enable replication to standard output
* \brief Enables replication to standard output
*
* Does nothing, as the std logger always write to standard output
*
* \param enable Unused argument
*/
void StdLogger::EnableStdReplication(bool enable)
@@ -40,9 +42,8 @@ namespace Nz
}
/*!
* \brief Get the standard output replication status
*
* Always returns true
* \brief Gets the standard output replication status
* \return Always returns true
*/
bool StdLogger::IsStdReplicationEnabled()
@@ -51,7 +52,8 @@ namespace Nz
}
/*!
* Write to the console
* \brief Writes to the console
*
* \param string The log to write to the console
*
* \see WriteError
@@ -64,7 +66,8 @@ namespace Nz
}
/*!
* Write an error to the console
* \brief Writes an error to the console
*
* \param type The error type
* \param error The error text
* \param line The line the error occurred

View File

@@ -11,22 +11,50 @@
namespace Nz
{
/*!
* \class Nz::Stream
* \brief Core class that represents a stream
*/
/*!
* \brief Destructs the object
*/
Stream::~Stream() = default;
/*!
* \brief Gets the directory of the stream
* \return Empty string (meant to be virtual)
*/
String Stream::GetDirectory() const
{
return String();
}
/*!
* \brief Gets the path of the stream
* \return Empty string (meant to be virtual)
*/
String Stream::GetPath() const
{
return String();
}
/*!
* \brief Reads characters in the stream
* \return Line containing characters
*
* \param lineSize Number of characters to read, if lineSize is 0, read as much as possible
*
* \remark Produces a NazaraWarning if cursor position could not be reset
*/
String Stream::ReadLine(unsigned int lineSize)
{
String line;
if (lineSize == 0) // Taille maximale indéterminée
if (lineSize == 0) // Maximal size undefined
{
const unsigned int bufferSize = 64;
@@ -63,7 +91,7 @@ namespace Nz
line.Set(lineSize, '\0');
std::size_t readSize = Read(&line[0], lineSize);
std::size_t pos = line.Find('\n');
if (pos <= readSize) // Faux uniquement si le caractère n'est pas présent (npos étant le plus grand entier)
if (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);
@@ -80,12 +108,26 @@ namespace Nz
return line;
}
/*!
* \brief Writes a ByteArray into the stream
* \return true if successful
*
* \param byteArray Bytes to write
*/
bool Stream::Write(const ByteArray& byteArray)
{
ByteArray::size_type size = byteArray.GetSize();
return Write(byteArray.GetConstBuffer(), size) == size;
}
/*!
* \brief Writes a String into the stream
* \return true if successful
*
* \param string String to write
*/
bool Stream::Write(const String& string)
{
String temp(string);

File diff suppressed because it is too large Load Diff

View File

@@ -7,17 +7,37 @@
namespace Nz
{
/*!
* \class Nz::StringStream
* \brief Core class that represents a stream of strings
*/
/*!
* \brief Constructs a StringStream object by default
*/
StringStream::StringStream() :
m_bufferSize(0)
{
}
/*!
* \brief Constructs a StringStream object with a string
*
* \param str First value of the stream
*/
StringStream::StringStream(const String& str) :
m_bufferSize(str.GetSize())
{
m_strings.push_back(str);
}
/*!
* \brief Gives a string representation
* \return A string representation of the object where every objects of the stream has been converted with Nz::String
*/
String StringStream::ToString() const
{
String string;
@@ -29,6 +49,13 @@ namespace Nz
return string;
}
/*!
* \brief Adds the representation of the boolean
* \return A reference to this
*
* \param boolean Boolean value
*/
StringStream& StringStream::operator<<(bool boolean)
{
m_strings.push_back(String::Boolean(boolean));
@@ -37,6 +64,13 @@ namespace Nz
return *this;
}
/*!
* \brief Adds the representation of the short
* \return A reference to this
*
* \param number Short value
*/
StringStream& StringStream::operator<<(short number)
{
m_strings.push_back(String::Number(number));
@@ -45,6 +79,13 @@ namespace Nz
return *this;
}
/*!
* \brief Adds the representation of the unsigned short
* \return A reference to this
*
* \param number Short value
*/
StringStream& StringStream::operator<<(unsigned short number)
{
m_strings.push_back(String::Number(number));
@@ -53,6 +94,13 @@ namespace Nz
return *this;
}
/*!
* \brief Adds the representation of the int
* \return A reference to this
*
* \param number Int value
*/
StringStream& StringStream::operator<<(int number)
{
m_strings.push_back(String::Number(number));
@@ -61,6 +109,13 @@ namespace Nz
return *this;
}
/*!
* \brief Adds the representation of the unsigned int
* \return A reference to this
*
* \param number Int value
*/
StringStream& StringStream::operator<<(unsigned int number)
{
m_strings.push_back(String::Number(number));
@@ -69,6 +124,13 @@ namespace Nz
return *this;
}
/*!
* \brief Adds the representation of the long
* \return A reference to this
*
* \param number Long value
*/
StringStream& StringStream::operator<<(long number)
{
m_strings.push_back(String::Number(number));
@@ -77,6 +139,13 @@ namespace Nz
return *this;
}
/*!
* \brief Adds the representation of the unsigned long
* \return A reference to this
*
* \param number Long value
*/
StringStream& StringStream::operator<<(unsigned long number)
{
m_strings.push_back(String::Number(number));
@@ -85,6 +154,13 @@ namespace Nz
return *this;
}
/*!
* \brief Adds the representation of the long long
* \return A reference to this
*
* \param number Long long value
*/
StringStream& StringStream::operator<<(long long number)
{
m_strings.push_back(String::Number(number));
@@ -93,6 +169,13 @@ namespace Nz
return *this;
}
/*!
* \brief Adds the representation of the unsigned long long
* \return A reference to this
*
* \param number Long long value
*/
StringStream& StringStream::operator<<(unsigned long long number)
{
m_strings.push_back(String::Number(number));
@@ -101,6 +184,13 @@ namespace Nz
return *this;
}
/*!
* \brief Adds the representation of the float
* \return A reference to this
*
* \param number Float value
*/
StringStream& StringStream::operator<<(float number)
{
m_strings.push_back(String::Number(number));
@@ -109,6 +199,13 @@ namespace Nz
return *this;
}
/*!
* \brief Adds the representation of the double
* \return A reference to this
*
* \param number Double value
*/
StringStream& StringStream::operator<<(double number)
{
m_strings.push_back(String::Number(number));
@@ -117,6 +214,13 @@ namespace Nz
return *this;
}
/*!
* \brief Adds the representation of the long double
* \return A reference to this
*
* \param number Long double value
*/
StringStream& StringStream::operator<<(long double number)
{
m_strings.push_back(String::Number(number));
@@ -125,6 +229,13 @@ namespace Nz
return *this;
}
/*!
* \brief Adds the representation of the char
* \return A reference to this
*
* \param character Char value
*/
StringStream& StringStream::operator<<(char character)
{
m_strings.push_back(String(character));
@@ -133,6 +244,13 @@ namespace Nz
return *this;
}
/*!
* \brief Adds the representation of the unsigned char
* \return A reference to this
*
* \param character Char value
*/
StringStream& StringStream::operator<<(unsigned char character)
{
m_strings.push_back(String(static_cast<char>(character)));
@@ -141,6 +259,13 @@ namespace Nz
return *this;
}
/*!
* \brief Adds the representation of the const char*
* \return A reference to this
*
* \param string String value
*/
StringStream& StringStream::operator<<(const char* string)
{
m_strings.push_back(string);
@@ -149,6 +274,13 @@ namespace Nz
return *this;
}
/*!
* \brief Adds the representation of the std::string
* \return A reference to this
*
* \param string String value
*/
StringStream& StringStream::operator<<(const std::string& string)
{
m_strings.push_back(string);
@@ -157,6 +289,13 @@ namespace Nz
return *this;
}
/*!
* \brief Adds the representation of the Nz::String
* \return A reference to this
*
* \param string String value
*/
StringStream& StringStream::operator<<(const String& string)
{
m_strings.push_back(string);
@@ -165,6 +304,13 @@ namespace Nz
return *this;
}
/*!
* \brief Adds the representation of the pointer
* \return A reference to this
*
* \param ptr Pointer value
*/
StringStream& StringStream::operator<<(const void* ptr)
{
m_strings.push_back(String::Pointer(ptr));
@@ -173,6 +319,11 @@ namespace Nz
return *this;
}
/*!
* \brief Converts this to Nz::String
* \return The string representation of the stream
*/
StringStream::operator String() const
{
return ToString();

View File

@@ -24,16 +24,39 @@ namespace Nz
unsigned int s_workerCount = 0;
}
/*!
* \class Nz::TaskScheduler<T>
* \brief Core class that represents a pool of threads
*
* \remark Initialized should be called first
*/
/*!
* \brief Gets the number of threads
* \return Number of threads, if none, the number of simulatenous threads on the processor is returned
*/
unsigned int TaskScheduler::GetWorkerCount()
{
return (s_workerCount > 0) ? s_workerCount : HardwareInfo::GetProcessorCount();
}
/*!
* \brief Initializes the TaskScheduler class
* \return true if everything is ok
*/
bool TaskScheduler::Initialize()
{
return TaskSchedulerImpl::Initialize(GetWorkerCount());
}
/*!
* \brief Runs the pending works
*
* \remark Produce a NazaraError if the class is not initialized
*/
void TaskScheduler::Run()
{
if (!Initialize())
@@ -49,6 +72,14 @@ namespace Nz
}
}
/*!
* \brief Sets the number of workers
*
* \param workerCount Number of simulatnous threads handling the tasks
*
* \remark Produce a NazaraError if the class is not initialized and NAZARA_CORE_SAFE is defined
*/
void TaskScheduler::SetWorkerCount(unsigned int workerCount)
{
#ifdef NAZARA_CORE_SAFE
@@ -62,12 +93,22 @@ namespace Nz
s_workerCount = workerCount;
}
/*!
* \brief Uninitializes the TaskScheduler class
*/
void TaskScheduler::Uninitialize()
{
if (TaskSchedulerImpl::IsInitialized())
TaskSchedulerImpl::Uninitialize();
}
/*!
* \brief Waits for tasks to be done
*
* \remark Produce a NazaraError if the class is not initialized
*/
void TaskScheduler::WaitForTasks()
{
if (!Initialize())
@@ -79,6 +120,15 @@ namespace Nz
TaskSchedulerImpl::WaitForTasks();
}
/*!
* \brief Adds a task on the pending list
*
* \param taskFunctor Functor represeting a task to be done
*
* \remark Produce a NazaraError if the class is not initialized
* \remark A task containing a call on this class is undefined behaviour
*/
void TaskScheduler::AddTaskFunctor(Functor* taskFunctor)
{
if (!Initialize())

View File

@@ -21,17 +21,36 @@
namespace Nz
{
/*!
* \class Nz::Thread<T>
* \brief Core class that represents a thread
*/
/*!
* \brief Constructs a Thread<T> object by default
*/
Thread::Thread() :
m_impl(nullptr)
{
}
/*!
* \brief Constructs a Thread<T> object by move semantic
*
* \param other Thread to move into this
*/
Thread::Thread(Thread&& other) noexcept :
m_impl(other.m_impl)
{
other.m_impl = nullptr;
}
/*!
* \brief Waits that the thread ends and then destroys this
*/
Thread::~Thread()
{
if (m_impl)
@@ -42,6 +61,10 @@ namespace Nz
}
}
/*!
* \brief Detaches the thread
*/
void Thread::Detach()
{
if (m_impl)
@@ -52,16 +75,32 @@ namespace Nz
}
}
/*!
* \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
@@ -77,6 +116,16 @@ namespace Nz
m_impl = nullptr;
}
/*!
* \brief Moves the other thread into this
* \return A reference to this
*
* \param thread Thread to move in this
*
* \remark Produce a NazaraError if no functor was assigned and NAZARA_CORE_SAFE is defined
* \remark And call std::terminate if no functor was assigned and NAZARA_CORE_SAFE is defined
*/
Thread& Thread::operator=(Thread&& thread)
{
#if NAZARA_CORE_SAFE
@@ -91,16 +140,33 @@ namespace Nz
return *this;
}
/*!
* \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 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);
@@ -108,41 +174,103 @@ namespace Nz
/*********************************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;

View File

@@ -11,20 +11,32 @@ namespace Nz
{
struct Character
{
UInt16 category; // Le type du caractère
UInt8 direction; // Le sens de lecure du caractère
UInt32 lowerCase; // Le caractère correspondant en minuscule
UInt32 titleCase; // Le caractère correspondant en titre
UInt32 upperCase; // Le caractère correspondant en majuscule
UInt16 category; // The type of the character
UInt8 direction; // The reading way of the character
UInt32 lowerCase; // The corresponding lower character
UInt32 titleCase; // The corresponding title character
UInt32 upperCase; // The corresponding upper character
};
}
#include <Nazara/Core/UnicodeData.hpp>
#else // Implémentation supportant la table ASCII
#else // Implementation handling ASCII table
namespace Nz
{
/*!
* \class Nz::Unicode
* \brief Core class that represents a Unicode character
*/
/*!
* \brief Gets the category of the character
* \return Unicode category
*
* \param character Character to get assignated category
*/
Unicode::Category Unicode::GetCategory(char32_t character)
{
switch (character)
@@ -188,6 +200,13 @@ namespace Nz
return Category_NoCategory;
}
/*!
* \brief Gets the direction of reading of the character
* \return Unicode direction
*
* \param character Character to get assignated direction
*/
Unicode::Direction Unicode::GetDirection(char32_t character)
{
switch (character)
@@ -347,6 +366,15 @@ namespace Nz
return Direction_Boundary_Neutral;
}
/*!
* \brief Gets the lower case of the character
* \return Unicode lower
*
* \param character Character to get assignated lower case
*
* \remark Only handling ASCII
*/
char32_t Unicode::GetLowercase(char32_t character)
{
if (character >= 'A' && character <= 'Z')
@@ -355,11 +383,29 @@ namespace Nz
return character;
}
/*!
* \brief Gets the title case of the character
* \return Unicode title
*
* \param character Character to get assignated title case
*
* \remark Only handling ASCII
*/
char32_t Unicode::GetTitlecase(char32_t character)
{
return GetUppercase(character);
}
/*!
* \brief Gets the upper case of the character
* \return Unicode upper
*
* \param character Character to get assignated upper case
*
* \remark Only handling ASCII
*/
char32_t Unicode::GetUppercase(char32_t character)
{
if (character >= 'a' && character <= 'z')

View File

@@ -136,7 +136,6 @@ namespace Nz
OpenEWMHConnection(sharedConnection);
}
NazaraNotice("Initialized: Display module");
return true;
}
@@ -208,8 +207,6 @@ namespace Nz
xcb_disconnect(sharedConnection);
}
NazaraNotice("Uninitialized: Display module");
}
xcb_window_t X11::XCBDefaultRootWindow(xcb_connection_t* connection)