diff --git a/include/Nazara/Core/Algorithm.hpp b/include/Nazara/Core/Algorithm.hpp index ae30f5065..5f8b8aa7f 100644 --- a/include/Nazara/Core/Algorithm.hpp +++ b/include/Nazara/Core/Algorithm.hpp @@ -27,11 +27,11 @@ namespace Nz template std::size_t CountOf(const T& c); template void HashCombine(std::size_t& seed, const T& v); - template - struct PointedType - { - using type = void; //< FIXME: I can't make SFINAE work - }; + template + struct PointedType + { + using type = void; //< FIXME: I can't make SFINAE work + }; template struct TypeTag {}; diff --git a/include/Nazara/Core/Algorithm.inl b/include/Nazara/Core/Algorithm.inl index c66bdb046..a9855c62c 100644 --- a/include/Nazara/Core/Algorithm.inl +++ b/include/Nazara/Core/Algorithm.inl @@ -30,6 +30,16 @@ namespace Nz } } + /*! + * \brief Applies the tuple to the function + * \return The result of the function + * + * \param fn Function + * \param t Tuple of arguments for the function + * + * \see Apply + */ + template auto Apply(F&& fn, Tuple&& t) { @@ -38,6 +48,17 @@ namespace Nz return Detail::ApplyImplFunc(std::forward(fn), std::forward(t), std::make_index_sequence()); } + /*! + * \brief Applies the tuple to the member function on an object + * \return The result of the member function called + * + * \param object Object of a class + * \param fn Member function + * \param t Tuple of arguments for the member function + * + * \see Apply + */ + template auto Apply(O& object, F&& fn, Tuple&& t) { @@ -46,15 +67,39 @@ namespace Nz return Detail::ApplyImplMethod(object, std::forward(fn), std::forward(t), std::make_index_sequence()); } + /*! + * \brief Computes the hash of a hashable object + * \return A bytearray which represents the hash + * + * \param hash Enumeration of type HashType + * \param v Object to hash, must be convertible to "Nz::String" + * + * \see ComputeHash + */ + template ByteArray ComputeHash(HashType hash, const T& v) { return ComputeHash(AbstractHash::Get(hash).get(), v); } + /*! + * \brief Computes the hash of a hashable object + * \return A bytearray which represents the hash + * + * \param hash Pointer to abstract hash + * \param v Object to hash, must be convertible to "Nz::String" + * + * \remark Produce a NazaraAssert if pointer to Abstracthash is invalid + * + * \see ComputeHash + */ + template ByteArray ComputeHash(AbstractHash* hash, const T& v) { + NazaraAssert(hash != nullptr, "Invalid abstracthash pointer"); + hash->Begin(); HashAppend(hash, v); @@ -62,19 +107,44 @@ namespace Nz return hash->End(); } - template + /*! + * \brief Returns the number of elements in a C-array + * \return The number of elements + * + * \param name C-array + * + * \see CountOf + */ + + template constexpr std::size_t CountOf(T(&name)[N]) noexcept { return N; } - template + /*! + * \brief Returns the number of elements in a container + * \return The number of elements + * + * \param c Container with the member function "size()" + * + * \see CountOf + */ + + template std::size_t CountOf(const T& c) { return c.size(); } - // Algorithme venant de CityHash par Google + /*! + * \brief Combines two hash in one + * + * \param seed First value that will be modified (expected to be 64bits) + * \param v Second value to hash + */ + + // Algorithm from CityHash by Google // http://stackoverflow.com/questions/8513911/how-to-create-a-good-hash-combine-with-64-bit-output-inspired-by-boosthash-co template void HashCombine(std::size_t& seed, const T& v) @@ -91,10 +161,20 @@ namespace Nz seed = static_cast(b * kMul); } - template struct PointedType {typedef T type;}; - template struct PointedType {typedef T type;}; - template struct PointedType {typedef T type;}; - template struct PointedType {typedef T type;}; + template struct PointedType {typedef T type;}; + template struct PointedType {typedef T type;}; + template struct PointedType {typedef T type;}; + template struct PointedType {typedef T type;}; + + /*! + * \brief Serializes a boolean + * \return true if serialization succedeed + * + * \param context Context for the serialization + * \param value Boolean to serialize + * + * \see Serialize, Unserialize + */ inline bool Serialize(SerializationContext& context, bool value) { @@ -113,6 +193,16 @@ namespace Nz return true; } + /*! + * \brief Serializes an arithmetic type + * \return true if serialization succedeed + * + * \param context Context for the serialization + * \param value Arithmetic type to serialize + * + * \see Serialize, Unserialize + */ + template std::enable_if_t::value, bool> Serialize(SerializationContext& context, T value) { @@ -131,6 +221,16 @@ namespace Nz return context.stream->Write(&value, sizeof(T)) == sizeof(T); } + /*! + * \brief Unserializes a boolean + * \return true if unserialization succedeed + * + * \param context Context for the unserialization + * \param value Pointer to boolean to unserialize + * + * \see Serialize, Unserialize + */ + inline bool Unserialize(SerializationContext& context, bool* value) { if (context.currentBitPos == 8) @@ -149,6 +249,18 @@ namespace Nz return true; } + /*! + * \brief Unserializes an arithmetic type + * \return true if unserialization succedeed + * + * \param context Context for the unserialization + * \param value Pointer to arithmetic type to serialize + * + * \remark Produce a NazaraAssert if pointer to value is invalid + * + * \see Serialize, Unserialize + */ + template std::enable_if_t::value, bool> Unserialize(SerializationContext& context, T* value) { diff --git a/include/Nazara/Core/Bitset.inl b/include/Nazara/Core/Bitset.inl index 68104b093..1b4cab200 100644 --- a/include/Nazara/Core/Bitset.inl +++ b/include/Nazara/Core/Bitset.inl @@ -16,12 +16,30 @@ namespace Nz { + /*! + * \class Nz::Bitset + * \brief Core class that represents a set of bits + * + * This class meets the requirements of Container, AllocatorAwareContainer, SequenceContainer + */ + + /*! + * \brief Constructs a Bitset object by default + */ + template Bitset::Bitset() : m_bitCount(0) { } + /*! + * \brief Constructs a Bitset object of bitCount bits to value val + * + * \param bitCount Number of bits + * \param val Value of those bits, by default false + */ + template Bitset::Bitset(unsigned int bitCount, bool val) : Bitset() @@ -29,12 +47,29 @@ namespace Nz Resize(bitCount, val); } + /*! + * \brief Constructs a Bitset object from the contents initialized with a copy of the null-terminated character string pointed to by bits + * + * \param bits Null-terminated character string containing only '0' and '1' + * + * \remark The length of the string is determined by the first null character, if there is no null character, the behaviour is undefined + */ + template Bitset::Bitset(const char* bits) : Bitset(bits, std::strlen(bits)) { } + /*! + * \brief Constructs a Bitset object from the contents initialized with a copy of the character string pointed to by bits takings the bitCount first characters + * + * \param bits Character string containing only '0' and '1' + * \param bitCount Number of characters to take into consideration + * + * \remark If the length of the string is inferior to the bitCount, the behaviour is undefined + */ + template Bitset::Bitset(const char* bits, unsigned int bitCount) : m_blocks(ComputeBlockCount(bitCount), 0U), @@ -45,12 +80,12 @@ namespace Nz switch (*bits++) { case '1': - // On adapte l'indice (inversion par rapport à la chaîne) + // We adapt the index (inversion in comparison to the string) Set(m_bitCount - i - 1, true); break; case '0': - // Tous les blocs ont été initialisés à zéro, rien à faire ici + // Each block is zero-initialised, nothing to do break; default: @@ -60,12 +95,24 @@ namespace Nz } } + /*! + * \brief Constructs a Bitset object from a Nz::String + * + * \param bits String containing only '0' and '1' + */ + template Bitset::Bitset(const String& bits) : Bitset(bits.GetConstBuffer(), bits.GetSize()) { } + /*! + * \brief Clears the content of the bitset, GetSize() is now equals to 0 + * + * \remark The memory allocated is not released + */ + template void Bitset::Clear() { @@ -73,6 +120,11 @@ namespace Nz m_blocks.clear(); } + /*! + * \brief Counts the number of bits set to 1 + * \return Number of bits set to 1 + */ + template unsigned int Bitset::Count() const { @@ -86,6 +138,10 @@ namespace Nz return count; } + /*! + * \brief Flips each bit of the bitset + */ + template void Bitset::Flip() { @@ -95,12 +151,26 @@ namespace Nz ResetExtraBits(); } + /*! + * \brief Finds the first bit set to one in the bitset + * \return Index of the first bit + */ + template unsigned int Bitset::FindFirst() const { return FindFirstFrom(0); } + /*! + * \brief Finds the next bit set to one in the bitset + * \return Index of the next bit if exists or npos + * + * \param bit Index of the bit, the search begin with bit + 1 + * + * \remark Produce a NazaraAssert if bit is greather than number of bits in bitset + */ + template unsigned int Bitset::FindNext(unsigned int bit) const { @@ -109,23 +179,32 @@ namespace Nz if (++bit >= m_bitCount) return npos; - // Le bloc du bit, l'indice du bit + // The block of the bit and its index unsigned int blockIndex = GetBlockIndex(bit); unsigned int bitIndex = GetBitIndex(bit); - // Récupération du bloc + // We get the block Block block = m_blocks[blockIndex]; - // On ignore les X premiers bits + // We ignore the X first bits block >>= bitIndex; - // Si le bloc n'est pas nul, c'est bon, sinon on doit chercher à partir du prochain bloc + // If the block is not empty, it's good, else we must keep trying with the next block if (block) return IntegralLog2Pot(block & -block) + bit; else return FindFirstFrom(blockIndex + 1); } + /*! + * \brief Gets the ith block + * \return Block in the bitset + * + * \param i Index of the block + * + * \remark Produce a NazaraAssert if i is greather than number of blocks in bitset + */ + template Block Bitset::GetBlock(unsigned int i) const { @@ -134,41 +213,71 @@ namespace Nz return m_blocks[i]; } + /*! + * \brief Gets the number of blocks + * \return Number of blocks + */ + template unsigned int Bitset::GetBlockCount() const { return m_blocks.size(); } + /*! + * \brief Gets the capacity of the bitset + * \return Capacity of the bitset + */ + template unsigned int Bitset::GetCapacity() const { return m_blocks.capacity()*bitsPerBlock; } + /*! + * \brief Gets the number of bits + * \return Number of bits + */ + template unsigned int Bitset::GetSize() const { return m_bitCount; } + /*! + * \brief Performs the "AND" operator between two bitsets + * + * \param a First bitset + * \param b Second bitset + * + * \remark The "AND" is performed with all the bits of the smallest bitset and the capacity of this is set to the largest of the two bitsets + */ + template void Bitset::PerformsAND(const Bitset& a, const Bitset& b) { std::pair minmax = std::minmax(a.GetBlockCount(), b.GetBlockCount()); - // On réinitialise nos blocs à zéro + // We reinitialise our blocks with zero m_blocks.clear(); m_blocks.resize(minmax.second, 0U); m_bitCount = std::max(a.GetSize(), b.GetSize()); - // Dans le cas du AND, nous pouvons nous arrêter à la plus petite taille (car x & 0 = 0) + // In case of the "AND", we can stop with the smallest size (because x & 0 = 0) for (unsigned int i = 0; i < minmax.first; ++i) m_blocks[i] = a.GetBlock(i) & b.GetBlock(i); ResetExtraBits(); } + /*! + * \brief Performs the "NOT" operator of the bitset + * + * \param a Bitset to negate + */ + template void Bitset::PerformsNOT(const Bitset& a) { @@ -181,6 +290,15 @@ namespace Nz ResetExtraBits(); } + /*! + * \brief Performs the "OR" operator between two bitsets + * + * \param a First bitset + * \param b Second bitset + * + * \remark The "OR" is performed with all the bits of the smallest bitset and the others are copied from the largest and the capacity of this is set to the largest of the two bitsets + */ + template void Bitset::PerformsOR(const Bitset& a, const Bitset& b) { @@ -201,6 +319,15 @@ namespace Nz ResetExtraBits(); } + /*! + * \brief Performs the "XOR" operator between two bitsets + * + * \param a First bitset + * \param b Second bitset + * + * \remark The "XOR" is performed with all the bits of the smallest bitset and the others are copied from the largest and the capacity of this is set to the largest of the two bitsets + */ + template void Bitset::PerformsXOR(const Bitset& a, const Bitset& b) { @@ -221,10 +348,16 @@ namespace Nz ResetExtraBits(); } + /*! + * \brief Checks if bitsets have one block in common + * + * \param bitset Bitset to test + */ + template bool Bitset::Intersects(const Bitset& bitset) const { - // On ne testera que les blocs en commun + // We only test the blocks in common unsigned int sharedBlocks = std::min(GetBlockCount(), bitset.GetBlockCount()); for (unsigned int i = 0; i < sharedBlocks; ++i) { @@ -237,40 +370,71 @@ namespace Nz return false; } + /*! + * \brief Reserves enough blocks to contain bitCount bits + * + * \param bitCount Number of bits to reserve + */ + template void Bitset::Reserve(unsigned int bitCount) { m_blocks.reserve(ComputeBlockCount(bitCount)); } + /*! + * \brief Resizes the bitset to the size of bitCount + * + * \param bitCount Number of bits to resize + * \param defaultVal Value of the bits if new size is greather than the old one + */ + template void Bitset::Resize(unsigned int bitCount, bool defaultVal) { - // On commence par changer la taille du conteneur, avec la valeur correcte d'initialisation + // We begin with changing the size of container, with the correct value of initialisation unsigned int lastBlockIndex = m_blocks.size() - 1; m_blocks.resize(ComputeBlockCount(bitCount), (defaultVal) ? fullBitMask : 0U); unsigned int remainingBits = GetBitIndex(m_bitCount); if (bitCount > m_bitCount && remainingBits > 0 && defaultVal) - // Initialisation des bits non-utilisés du dernier bloc avant le changement de taille + // Initialisation of unused bits in the last block before the size change m_blocks[lastBlockIndex] |= fullBitMask << remainingBits; m_bitCount = bitCount; ResetExtraBits(); } + /*! + * \brief Resets the bitset to zero bits + */ + template void Bitset::Reset() { Set(false); } + /*! + * \brief Resets the bit at the index + * + * \param bit Index of the bit + * + * \see UnboundReset + */ + template void Bitset::Reset(unsigned int bit) { Set(bit, false); } + /*! + * \brief Sets the bitset to val + * + * \param val Value of the bits + */ + template void Bitset::Set(bool val) { @@ -279,6 +443,17 @@ namespace Nz ResetExtraBits(); } + /*! + * \brief Sets the bit at the index + * + * \param bit Index of the bit + * \param val Value of the bit + * + * \remark Produce a NazaraAssert if bit is greather than number of bits in bitset + * + * \see UnboundSet + */ + template void Bitset::Set(unsigned int bit, bool val) { @@ -287,11 +462,19 @@ namespace Nz Block& block = m_blocks[GetBlockIndex(bit)]; Block mask = Block(1U) << GetBitIndex(bit); - // Activation du bit sans branching + // Activation of the bit without branching // https://graphics.stanford.edu/~seander/bithacks.html#ConditionalSetOrClearBitsWithoutBranching block = (block & ~mask) | (-val & mask); } + /*! + * \brief Set the ith block + * + * \param i Index of the block + * \param block Block to set + * + * \remark Produce a NazaraAssert if i is greather than number of blocks in bitset + */ template void Bitset::SetBlock(unsigned int i, Block block) { @@ -302,6 +485,12 @@ namespace Nz ResetExtraBits(); } + /*! + * \brief Swaps the two bitsets + * + * \param bitset Other bitset to swap + */ + template void Bitset::Swap(Bitset& bitset) { @@ -309,6 +498,17 @@ namespace Nz std::swap(m_blocks, bitset.m_blocks); } + /*! + * \brief Tests the ith bit + * \return true if bit is set + * + * \param bit Index of the bit + * + * \remark Produce a NazaraAssert if bit is greather than number of bits in bitset + * + * \see UnboundTest + */ + template bool Bitset::Test(unsigned int bit) const { @@ -317,22 +517,32 @@ namespace Nz return (m_blocks[GetBlockIndex(bit)] & (Block(1U) << GetBitIndex(bit))) != 0; } + /*! + * \brief Tests each block + * \return true if each block is set + */ + template bool Bitset::TestAll() const { - // Cas particulier du dernier bloc + // Special case for the last block Block lastBlockMask = GetLastBlockMask(); for (unsigned int i = 0; i < m_blocks.size(); ++i) { Block mask = (i == m_blocks.size() - 1) ? lastBlockMask : fullBitMask; - if (m_blocks[i] == mask) // Les extra bits sont à zéro, on peut donc tester sans procéder à un masquage + if (m_blocks[i] == mask) // The extra bits are set to zero, thus we can't test without proceeding with a mask return false; } return true; } + /*! + * \brief Tests if one bit is set + * \return true if one bit is set + */ + template bool Bitset::TestAny() const { @@ -348,12 +558,24 @@ namespace Nz return false; } + /*! + * \brief Tests if one bit is not set + * \return true if one bit is not set + */ + template bool Bitset::TestNone() const { return !TestAny(); } + /*! + * \brief Converts the bitset to template type + * \return The conversion of the bitset + * + * \remark Produce a NazaraAssert if the template type can not hold the number of bits + */ + template template T Bitset::To() const @@ -369,6 +591,11 @@ namespace Nz return value; } + /*! + * \brief Gives a string representation + * \return A string representation of the object with only '0' and '1' + */ + template String Bitset::ToString() const { @@ -383,12 +610,33 @@ namespace Nz return str; } + /*! + * \brief Resets the bit at the index + * + * \param bit Index of the bit + * + * \remark if bit is greather than the number of bits, the bitset is enlarged and the added bits are set to false + * + * \see Reset + */ + template void Bitset::UnboundedReset(unsigned int bit) { UnboundedSet(bit, false); } + /*! + * \brief Sets the bit at the index + * + * \param bit Index of the bit + * \param val Value of the bit + * + * \remark if bit is greather than the number of bits, the bitset is enlarged and the added bits are set to false and the one at bit is set to val + * + * \see Set + */ + template void Bitset::UnboundedSet(unsigned int bit, bool val) { @@ -402,6 +650,15 @@ namespace Nz } } + /*! + * \brief Tests the ith bit + * \return true if bit is set + * + * \param bit Index of the bit + * + * \see Test + */ + template bool Bitset::UnboundedTest(unsigned int bit) const { @@ -411,18 +668,33 @@ namespace Nz return false; } + /*! + * \brief Gets the ith bit + * \return bit in ith position + */ + template typename Bitset::Bit Bitset::operator[](int index) { return Bit(m_blocks[GetBlockIndex(index)], Block(1U) << GetBitIndex(index)); } + /*! + * \brief Gets the ith bit + * \return bit in ith position + */ + template bool Bitset::operator[](int index) const { return Test(index); } + /*! + * \brief Negates the bitset + * \return A new bitset which is the "NOT" of this bitset + */ + template Bitset Bitset::operator~() const { @@ -432,6 +704,13 @@ namespace Nz return bitset; } + /*! + * \brief Sets this bitset from a Nz::String + * \return A reference to this + * + * \param bits String containing only '0' and '1' + */ + template Bitset& Bitset::operator=(const String& bits) { @@ -441,6 +720,13 @@ namespace Nz return *this; } + /*! + * \brief Performs an "AND" with another bitset + * \return A reference to this + * + * \param bitset Other bitset + */ + template Bitset& Bitset::operator&=(const Bitset& bitset) { @@ -449,6 +735,13 @@ namespace Nz return *this; } + /*! + * \brief Performs an "OR" with another bitset + * \return A reference to this + * + * \param bitset Other bitset + */ + template Bitset& Bitset::operator|=(const Bitset& bitset) { @@ -457,6 +750,13 @@ namespace Nz return *this; } + /*! + * \brief Performs an "XOR" with another bitset + * \return A reference to this + * + * \param bitset Other bitset + */ + template Bitset& Bitset::operator^=(const Bitset& bitset) { @@ -465,13 +765,20 @@ namespace Nz return *this; } + /*! + * \brief Finds the position of the first bit set to true after the blockIndex + * \return The position of the bit + * + * \param blockIndex Index of the block + */ + template unsigned int Bitset::FindFirstFrom(unsigned int blockIndex) const { if (blockIndex >= m_blocks.size()) return npos; - // On cherche le premier bloc non-nul + // We are looking for the first non-null block unsigned int i = blockIndex; for (; i < m_blocks.size(); ++i) { @@ -479,22 +786,31 @@ namespace Nz break; } - // Est-ce qu'on a un bloc non-nul ? + // Do we have a non-null block ? if (i == m_blocks.size()) return npos; Block block = m_blocks[i]; - // Calcul de la position du LSB dans le bloc (et ajustement de la position) + // Compute the position of LSB in the block (and adjustement of the position) return IntegralLog2Pot(block & -block) + i*bitsPerBlock; } + /*! + * \brief Gets the mask associated to the last block + * \return Block which represents the mask + */ + template Block Bitset::GetLastBlockMask() const { return (Block(1U) << GetBitIndex(m_bitCount)) - 1U; } + /*! + * \brief Sets to '0' the last bits unassigned in the last block + */ + template void Bitset::ResetExtraBits() { @@ -503,24 +819,43 @@ namespace Nz m_blocks.back() &= mask; } + /*! + * \brief Computes the block count with the index of the bit + * \return Number of the blocks to contain the bit + */ + template unsigned int Bitset::ComputeBlockCount(unsigned int bitCount) { return GetBlockIndex(bitCount) + ((GetBitIndex(bitCount) != 0U) ? 1U : 0U); } + /*! + * \brief Computes the bit position in the block + * \return Index of the bit in the block + */ + template unsigned int Bitset::GetBitIndex(unsigned int bit) { return bit & (bitsPerBlock - 1U); // bit % bitsPerBlock } + /*! + * \brief Computes the block index with the index of the bit + * \return Index of the block containing the bit + */ + template unsigned int Bitset::GetBlockIndex(unsigned int bit) { return bit / bitsPerBlock; } + /*! + * \brief Flips the bit + * \return A reference to this + */ template typename Bitset::Bit& Bitset::Bit::Flip() @@ -530,12 +865,24 @@ namespace Nz return *this; } + /*! + * \brief Resets the bit + * \return A reference to this + */ + template typename Bitset::Bit& Bitset::Bit::Reset() { return Set(false); } + /*! + * \brief Sets the bit to a value + * \return A reference to this + * + * \param val Value of the bit + */ + template typename Bitset::Bit& Bitset::Bit::Set(bool val) { @@ -545,47 +892,85 @@ namespace Nz return *this; } + /*! + * \brief Tests the bit + * \return A reference to this + */ + template bool Bitset::Bit::Test() const { return m_block & m_mask; } + /*! + * \brief Gets the adress of the bit + * \return Nullptr + * + * \see std::addressof + */ + template template void* Bitset::Bit::operator&() const { - // Le template est nécessaire pour ne planter la compilation qu'à l'utilisation + // The template is necessary to make it fail only when used static_assert(!BadCall, "It is impossible to take the address of a bit in a bitset"); return nullptr; } + /*! + * \brief Converts this to bool + * \return true if bit set to '1' + */ + template Bitset::Bit::operator bool() const { return Test(); } + /*! + * \brief Sets the bit to a value + * \return A reference to this + * + * \param val Value of the bit + */ + template typename Bitset::Bit& Bitset::Bit::operator=(bool val) { return Set(val); } + /*! + * \brief Sets the bit to the value of another one + * \return A reference to this + * + * \param bit Other bit + */ + template typename Bitset::Bit& Bitset::Bit::operator=(const Bit& bit) { return Set(bit); } + /*! + * \brief Performs the operator "OR" on this bit with a boolean + * \return A reference to this + * + * \param val Value + */ + template typename Bitset::Bit& Bitset::Bit::operator|=(bool val) { - // Version sans branching: + // Version without branching: Set((val) ? true : Test()); - // Avec branching: + // With branching: /* if (val) Set(); @@ -594,13 +979,20 @@ namespace Nz return *this; } + /*! + * \brief Performs the operator "AND" on this bit with a boolean + * \return A reference to this + * + * \param val Value + */ + template typename Bitset::Bit& Bitset::Bit::operator&=(bool val) { - // Version sans branching: + // Version without branching: Set((val) ? Test() : false); - // Avec branching: + // With branching: /* if (!val) Reset(); @@ -609,13 +1001,20 @@ namespace Nz return *this; } + /*! + * \brief Performs the operator "XOR" on this bit with a boolean + * \return A reference to this + * + * \param val Value + */ + template typename Bitset::Bit& Bitset::Bit::operator^=(bool val) { - // Version sans branching: + // Version without branching: Set((val) ? !Test() : Test()); - // Avec branching: + // With branching: /* if (val) Flip(); @@ -624,13 +1023,20 @@ namespace Nz return *this; } + /*! + * \brief Performs the operator "RESET" on this bit with a boolean + * \return A reference to this + * + * \param val Value + */ + template typename Bitset::Bit& Bitset::Bit::operator-=(bool val) { - // Version sans branching: + // Version without branching: Set((val) ? false : Test()); - // Avec branching: + // With branching: /* if (val) Reset(); @@ -639,26 +1045,35 @@ namespace Nz return *this; } + /*! + * \brief Compares two bitsets + * \return true if the two bitsets are the same + * + * \param lhs First bitset to compare with + * \param rhs Other bitset to compare with + * + * \remark If one is bigger, they are equal only if the largest has the last bit set to '0' + */ + template bool operator==(const Bitset& lhs, const Bitset& rhs) { - // La comparaison part du principe que (uint8) 00001100 == (uint16) 00000000 00001100 - // et conserve donc cette propriété + // The comparison uses that (uint8) 00001100 == (uint16) 00000000 00001100 + // and thus conserve this property const Bitset& greater = (lhs.GetBlockCount() > rhs.GetBlockCount()) ? lhs : rhs; const Bitset& lesser = (lhs.GetBlockCount() > rhs.GetBlockCount()) ? rhs : lhs; unsigned int maxBlockCount = greater.GetBlockCount(); unsigned int minBlockCount = lesser.GetBlockCount(); - // Nous testons les blocs en commun pour vérifier l'égalité des bits + // We test the blocks in common to check the equality of bits for (unsigned int i = 0; i < minBlockCount; ++i) { if (lhs.GetBlock(i) != rhs.GetBlock(i)) return false; } - // Nous vérifions maintenant les blocs que seul le plus grand bitset possède, pour prétendre à l'égalité - // ils doivent tous être nuls + // Now we check for the blocks that only the biggest bitset owns, and to be equal, they must be set to '0' for (unsigned int i = minBlockCount; i < maxBlockCount; ++i) if (greater.GetBlock(i)) return false; @@ -666,12 +1081,28 @@ namespace Nz return true; } + /*! + * \brief Compares two bitsets + * \return false if the two bitsets are the same + * + * \param lhs First bitset to compare with + * \param rhs Other bitset to compare with + */ + template bool operator!=(const Bitset& lhs, const Bitset& rhs) { return !(lhs == rhs); } + /*! + * \brief Compares two bitsets + * \return true if the binary number represented by the lhs bitset is smaller + * + * \param lhs First bitset to compare with + * \param rhs Other bitset to compare with + */ + template bool operator<(const Bitset& lhs, const Bitset& rhs) { @@ -699,24 +1130,56 @@ namespace Nz return false; // They are equal } + /*! + * \brief Compares two bitsets + * \return true if the binary number represented by the lhs bitset is smaller or equal + * + * \param lhs First bitset to compare with + * \param rhs Other bitset to compare with + */ + template bool operator<=(const Bitset& lhs, const Bitset& rhs) { return lhs < rhs || lhs == rhs; } + /*! + * \brief Compares two bitsets + * \return true if the binary number represented by the lhs bitset is greather + * + * \param lhs First bitset to compare with + * \param rhs Other bitset to compare with + */ + template bool operator>(const Bitset& lhs, const Bitset& rhs) { return rhs < lhs; } + /*! + * \brief Compares two bitsets + * \return true if the binary number represented by the lhs bitset is greather or equal + * + * \param lhs First bitset to compare with + * \param rhs Other bitset to compare with + */ + template bool operator>=(const Bitset& lhs, const Bitset& rhs) { return rhs <= lhs; } + /*! + * \brief Performs the operator "AND" between two bitsets + * \return The result of operator "AND" + * + * \param lhs First bitset + * \param rhs Second bitset + */ + template Bitset operator&(const Bitset& lhs, const Bitset& rhs) { @@ -726,6 +1189,14 @@ namespace Nz return bitset; } + /*! + * \brief Performs the operator "OR" between two bitsets + * \return The result of operator "OR" + * + * \param lhs First bitset + * \param rhs Second bitset + */ + template Bitset operator|(const Bitset& lhs, const Bitset& rhs) { @@ -735,6 +1206,14 @@ namespace Nz return bitset; } + /*! + * \brief Performs the operator "XOR" between two bitsets + * \return The result of operator "XOR" + * + * \param lhs First bitset + * \param rhs Second bitset + */ + template Bitset operator^(const Bitset& lhs, const Bitset& rhs) { @@ -748,6 +1227,13 @@ namespace Nz namespace std { + /*! + * \brief Swaps two bitsets, specialisation of std + * + * \param lhs First bitset + * \param rhs Second bitset + */ + template void swap(Nz::Bitset& lhs, Nz::Bitset& rhs) { diff --git a/include/Nazara/Core/ByteArray.inl b/include/Nazara/Core/ByteArray.inl index 1597758fd..2a8ab59a8 100644 --- a/include/Nazara/Core/ByteArray.inl +++ b/include/Nazara/Core/ByteArray.inl @@ -6,59 +6,141 @@ namespace Nz { + /*! + * \brief Constructs a ByteArray object with a reserved size + * + * \param n Space reserved + */ + inline ByteArray::ByteArray(size_type n) : m_array() { m_array.reserve(n); } + /*! + * \brief Constructs a ByteArray object with a raw memory and a size + * + * \param ptr Pointer to raw memory + * \param n Size that can be accessed + * + * \remark If preallocated space of ptr is less than the size, the behaviour is undefined + */ + inline ByteArray::ByteArray(const void* buffer, size_type n) : m_array(static_cast(buffer), static_cast(buffer) + n) { } + /*! + * \brief Constructs a ByteArray object with n times the same value + * + * \param n Number of repetitions + * \param value Value to repeat + */ + inline ByteArray::ByteArray(size_type n, const value_type value) : m_array(n, value) { } + /*! + * \brief Constructs a ByteArray object from two iterators + * + * \param first First iterator + * \param last Second iterator + */ + template ByteArray::ByteArray(InputIterator first, InputIterator last) : m_array(first, last) { } + /*! + * \brief Appends the content of raw memory + * + * \param ptr Constant pointer to raw memory + * \param n Size that can be read + * + * \remark If preallocated space of ptr is less than the size, the behaviour is undefined + * + * \see Insert + */ + inline ByteArray::iterator ByteArray::Append(const void* buffer, size_type n) { return Insert(end(), static_cast(buffer), static_cast(buffer) + n); } + /*! + * \brief Appends another array of bytes + * + * \param other ByteArray to add + * + * \see Insert + */ + inline ByteArray::iterator ByteArray::Append(const ByteArray& other) { return Insert(end(), other.begin(), other.end()); } + /*! + * \brief Assigns this with n times the same value + * + * \param n Number of repetitions + * \param value Value to repeat + */ + inline void ByteArray::Assign(size_type n, value_type value) { m_array.assign(n, value); } + /*! + * \brief Assigns this with the content between two iterators + * + * \param first First iterator + * \param last Second iterator + */ + template void ByteArray::Assign(InputIterator first, InputIterator last) { m_array.assign(first, last); } + /*! + * \brief Gets last element + * \return A reference to last element + * + * \remark If ByteArray is empty, behaviour is undefined + */ + inline ByteArray::reference ByteArray::Back() { return m_array.back(); } + /*! + * \brief Gets last element + * \return A constant reference to last element + * + * \remark If ByteArray is empty, behaviour is undefined + */ + inline ByteArray::const_reference ByteArray::Back() const { return m_array.back(); } + /*! + * \brief Clears the content of the string + * + * \param keepBuffer Should the buffer be kept + */ + inline void ByteArray::Clear(bool keepBuffer) { m_array.clear(); @@ -66,142 +148,326 @@ namespace Nz m_array.shrink_to_fit(); } + /*! + * \brief Erases an element from the byte array + * + * \param pos Iterator to the element + */ + inline ByteArray::iterator ByteArray::Erase(const_iterator pos) { return m_array.erase(pos); } + /*! + * \brief Erases the elements between the two pointers from the byte array + * + * \param first First iterator + * \param last Second iterator + */ + inline ByteArray::iterator ByteArray::Erase(const_iterator first, const_iterator last) { return m_array.erase(first, last); } + /*! + * \brief Gets first element + * \return A reference to first element + * + * \remark If ByteArray is empty, behaviour is undefined + */ + inline ByteArray::reference ByteArray::Front() { return m_array.front(); } + /*! + * \brief Gets first element + * \return A constant reference to first element + * + * \remark If ByteArray is empty, behaviour is undefined + */ + inline ByteArray::const_reference ByteArray::Front() const { return m_array.front(); } + /*! + * \brief Gets the internal allocator of the byte array + * \return Allocator + */ + inline ByteArray::allocator_type ByteArray::GetAllocator() const { return m_array.get_allocator(); } + /*! + * \brief Gets the raw buffer + * \return Raw buffer + */ + inline ByteArray::pointer ByteArray::GetBuffer() { return m_array.data(); } + /*! + * \brief Gets the capacity of the byte array + * \return Capacity of the byte array + */ + inline ByteArray::size_type ByteArray::GetCapacity() const noexcept { return m_array.capacity(); } + /*! + * \brief Gets the raw buffer + * \return Raw buffer + */ + inline ByteArray::const_pointer ByteArray::GetConstBuffer() const { return m_array.data(); } + /*! + * \brief Gets the maximal size supported by the byte array + * \return Biggest size handled + */ + inline ByteArray::size_type ByteArray::GetMaxSize() const noexcept { return m_array.max_size(); } + /*! + * \brief Gets the size of the byte array + * \return Size of the byte array + */ + inline ByteArray::size_type ByteArray::GetSize() const noexcept { return m_array.size(); } + /*! + * \brief Returns a sub byte array of the byte array + * \return Sub byte array + * + * \param startPos First iterator + * \param endPos Second iterator + */ + inline ByteArray ByteArray::GetSubArray(const_iterator startPos, const_iterator endPos) const { return ByteArray(startPos, endPos); } + /*! + * \brief Inserts the content of raw memory at the iterator position + * + * \param pos Iterator to the position + * \param buffer Constant pointer to raw memory + * \param n Size that can be read + * + * \remark If preallocated space of ptr is less than the size, the behaviour is undefined + */ + inline ByteArray::iterator ByteArray::Insert(const_iterator pos, const void* buffer, size_type n) { return m_array.insert(pos, static_cast(buffer), static_cast(buffer) + n); } + /*! + * \brief Inserts the content of another byte array at the iterator position + * + * \param pos Iterator to the position + * \param other Other byte array + */ + inline ByteArray::iterator ByteArray::Insert(const_iterator pos, const ByteArray& other) { return m_array.insert(pos, other.begin(), other.end()); } + /*! + * \brief Inserts n times the same value at the iterator position + * + * \param pos Iterator to the position + * \param n Number of repetitions + * \param value Value to repeat + */ + inline ByteArray::iterator ByteArray::Insert(const_iterator pos, size_type n, value_type byte) { return m_array.insert(pos, n, byte); } + /*! + * \brief Inserts the content from two iterators at the iterator position + * + * \param pos Iterator to the position + * \param first First iterator + * \param last Second iterator + */ + template ByteArray::iterator ByteArray::Insert(const_iterator pos, InputIterator first, InputIterator last) { return m_array.insert(pos, first, last); } + /*! + * \brief Checks whether the byte array is empty + * \return true if byte array is empty + */ + inline bool ByteArray::IsEmpty() const noexcept { return m_array.empty(); } + /*! + * \brief Erases the last element + * + * \remark If byte array is empty, the behaviour is undefined + */ + inline void ByteArray::PopBack() { Erase(end() - 1); } + /*! + * \brief Erases the first element + * + * \remark If byte array is empty, the behaviour is undefined + */ + inline void ByteArray::PopFront() { Erase(begin()); } + /*! + * \brief Prepends the content of raw memory + * + * \param ptr Constant pointer to raw memory + * \param n Size that can be read + * + * \remark If preallocated space of ptr is less than the size, the behaviour is undefined + * + * \see Insert + */ + inline ByteArray::iterator ByteArray::Prepend(const void* buffer, size_type n) { return Insert(begin(), buffer, n); } + /*! + * \brief Prepends another array of bytes + * + * \param other ByteArray to add + * + * \see Insert + */ + inline ByteArray::iterator ByteArray::Prepend(const ByteArray& other) { return Insert(begin(), other); } + /*! + * \brief Pushes the byte at the end + * + * \param byte Byte to add + */ + inline void ByteArray::PushBack(const value_type byte) { m_array.push_back(byte); } + /*! + * \brief Pushes the byte at the beginning + * + * \param byte Byte to add + */ + inline void ByteArray::PushFront(const value_type byte) { m_array.insert(begin(), 1, byte); } + /*! + * \brief Reserves enough memory for the buffer size + * + * \param bufferSize Size of the buffer to allocate + * + * \remark If bufferSize is smaller than the old one, nothing is done + */ + inline void ByteArray::Reserve(size_type bufferSize) { m_array.reserve(bufferSize); } + /*! + * \brief Resizes the string + * \return A reference to this + * + * \param newSize Target size + */ + inline void ByteArray::Resize(size_type newSize) { m_array.resize(newSize); } + /*! + * \brief Resizes the string + * \return A reference to this + * + * \param newSize Target size + * \param byte Byte to add if newSize is greather than actual size + */ + inline void ByteArray::Resize(size_type newSize, const value_type byte) { m_array.resize(newSize, byte); } + /*! + * \brief Releases the excedent memory + */ + inline void ByteArray::ShrinkToFit() { m_array.shrink_to_fit(); } + /*! + * \brief Swaps the content with the other byte array + * + * \param other Other byte array to swap with + */ + inline void ByteArray::Swap(ByteArray& other) { m_array.swap(other.m_array); } + /*! + * \brief Gives a string representation in base 16 + * \return String in base 16 + */ + inline String ByteArray::ToHex() const { std::size_t length = m_array.size() * 2; @@ -213,76 +479,153 @@ namespace Nz return hexOutput; } + /*! + * \brief Gives a string representation + * \return String where each byte is converted to char + */ + inline String ByteArray::ToString() const { return String(reinterpret_cast(GetConstBuffer()), GetSize()); } + /*! + * \brief Returns an iterator pointing to the beggining of the string + * \return Beggining of the string + */ + inline ByteArray::iterator ByteArray::begin() noexcept { return m_array.begin(); } + /*! + * \brief Returns an iterator pointing to the beggining of the string + * \return Beggining of the string + */ + inline ByteArray::const_iterator ByteArray::begin() const noexcept { return m_array.begin(); } + /*! + * \brief Returns a constant iterator pointing to the beggining of the string + * \return Beggining of the string + */ + inline ByteArray::const_iterator ByteArray::cbegin() const noexcept { return m_array.cbegin(); } + /*! + * \brief Returns a constant iterator pointing to the end of the string + * \return End of the string + */ + inline ByteArray::const_iterator ByteArray::cend() const noexcept { return m_array.cend(); } + /*! + * \brief Returns a constant reversed iterator pointing to the beggining of the string + * \return Beggining of the string + */ + inline ByteArray::const_reverse_iterator ByteArray::crbegin() const noexcept { return m_array.crbegin(); } + /*! + * \brief Returns a constant reversed iterator pointing to the end of the string + * \return End of the string + */ + inline ByteArray::const_reverse_iterator ByteArray::crend() const noexcept { return m_array.crend(); } + /*! + * \brief Checks whether the byte array is empty + * \return true if byte array is empty + */ + inline bool ByteArray::empty() const noexcept { return m_array.empty(); } + /*! + * \brief Returns an iterator pointing to the end of the string + * \return End of the string + */ + inline ByteArray::iterator ByteArray::end() noexcept { return m_array.end(); } + /*! + * \brief Returns an iterator pointing to the end of the string + * \return End of the string + */ + inline ByteArray::const_iterator ByteArray::end() const noexcept { return m_array.end(); } + /*! + * \brief Returns a reversed iterator pointing to the beggining of the string + * \return Beggining of the string + */ + inline ByteArray::reverse_iterator ByteArray::rbegin() noexcept { return m_array.rbegin(); } + /*! + * \brief Returns a reversed iterator pointing to the beggining of the string + * \return Beggining of the string + */ + inline ByteArray::const_reverse_iterator ByteArray::rbegin() const noexcept { return m_array.rbegin(); } + /*! + * \brief Returns a reversed iterator pointing to the end of the string + * \return End of the string + */ + inline ByteArray::reverse_iterator ByteArray::rend() noexcept { return m_array.rend(); } + /*! + * \brief Gets the size of the byte array + * \return Size of the byte array + */ + inline ByteArray::size_type ByteArray::size() const noexcept { return GetSize(); } + /*! + * \brief Gets the ith byte + * \return A reference to the byte at the ith position + * + * \remark Produces a NazaraAssert if pos is greather than the size + */ + inline ByteArray::reference ByteArray::operator[](size_type pos) { NazaraAssert(pos < GetSize(), "Index out of range"); @@ -290,6 +633,13 @@ namespace Nz return m_array[pos]; } + /*! + * \brief Gets the ith byte + * \return A constant reference to the byte at the ith position + * + * \remark Produces a NazaraAssert if pos is greather than the size + */ + inline ByteArray::const_reference ByteArray::operator[](size_type pos) const { NazaraAssert(pos < GetSize(), "Index out of range"); @@ -297,6 +647,13 @@ namespace Nz return m_array[pos]; } + /*! + * \brief Concatenates the byte array to another + * \return ByteArray which is the result of the concatenation + * + * \param other ByteArray to add + */ + inline ByteArray ByteArray::operator+(const ByteArray& other) const { ByteArray tmp(*this); @@ -305,6 +662,13 @@ namespace Nz return tmp; } + /*! + * \brief Concatenates the byte array to this byte array + * \return A reference to this + * + * \param other ByteArray to add + */ + inline ByteArray& ByteArray::operator+=(const ByteArray& other) { Append(other); @@ -312,31 +676,79 @@ namespace Nz return *this; } + /*! + * \brief Checks whether the first byte array is equal to the second byte array + * \return true if it is the case + * + * \param first ByteArray to compare in left hand side + * \param second ByteArray to compare in right hand side + */ + inline bool ByteArray::operator==(const ByteArray& rhs) const { return m_array == rhs.m_array; } + /*! + * \brief Checks whether the first byte array is equal to the second byte array + * \return false if it is the case + * + * \param first ByteArray to compare in left hand side + * \param second ByteArray to compare in right hand side + */ + inline bool ByteArray::operator!=(const ByteArray& rhs) const { return !operator==(rhs); } + /*! + * \brief Checks whether the first byte array is less than the second byte array + * \return true if it is the case + * + * \param first ByteArray to compare in left hand side + * \param second ByteArray to compare in right hand side + */ + inline bool ByteArray::operator<(const ByteArray& rhs) const { return m_array < rhs.m_array; } + /*! + * \brief Checks whether the first byte array is less or equal than the second byte array + * \return true if it is the case + * + * \param first ByteArray to compare in left hand side + * \param second ByteArray to compare in right hand side + */ + inline bool ByteArray::operator<=(const ByteArray& rhs) const { return m_array <= rhs.m_array; } + /*! + * \brief Checks whether the first byte array is greather than the second byte array + * \return true if it is the case + * + * \param first ByteArray to compare in left hand side + * \param second ByteArray to compare in right hand side + */ + inline bool ByteArray::operator>(const ByteArray& rhs) const { return m_array > rhs.m_array; } + /*! + * \brief Checks whether the first byte array is greather or equal than the second byte array + * \return true if it is the case + * + * \param first ByteArray to compare in left hand side + * \param second ByteArray to compare in right hand side + */ + inline bool ByteArray::operator>=(const ByteArray& rhs) const { return m_array >= rhs.m_array; @@ -351,6 +763,13 @@ namespace Nz namespace std { + /*! + * \brief Swaps two byte arrays, specialisation of std + * + * \param lhs First byte array + * \param rhs Second byte array + */ + inline void swap(Nz::ByteArray& lhs, Nz::ByteArray& rhs) { lhs.Swap(rhs); diff --git a/include/Nazara/Core/ByteStream.inl b/include/Nazara/Core/ByteStream.inl index f6e765175..83062d3ba 100644 --- a/include/Nazara/Core/ByteStream.inl +++ b/include/Nazara/Core/ByteStream.inl @@ -7,11 +7,25 @@ namespace Nz { + /*! + * \brief Constructs a ByteStream object with a stream + * + * \remark Produces a NazaraAssert if stream is invalid + */ + inline ByteStream::ByteStream(Stream* stream) { + NazaraAssert(stream, "Invalid stream"); + m_context.stream = stream; } + /*! + * \brief Constructs a ByteStream object by move semantic + * + * \param stream ByteStream to move into this + */ + inline ByteStream::ByteStream(ByteStream&& stream) : m_ownedStream(std::move(stream.m_ownedStream)), m_context(stream.m_context) @@ -19,17 +33,35 @@ namespace Nz stream.m_context.stream = nullptr; } + /*! + * \brief Destructs the object and calls FlushBits + * + * \remark Produces a NazaraWarning if flush did not work + * + * \see FlushBits + */ + inline ByteStream::~ByteStream() { if (!FlushBits()) NazaraWarning("Failed to flush bits at serializer destruction"); } + /*! + * \brief Gets the stream endianness + * \return Type of the endianness + */ + inline Endianness ByteStream::GetDataEndianness() const { return m_context.endianness; } + /*! + * \brief Gets the size of the byte stream + * \return Size of the stream + */ + inline Nz::UInt64 ByteStream::GetSize() const { if (m_context.stream) @@ -38,11 +70,21 @@ namespace Nz return 0; } + /*! + * \brief Gets the internal stream + * \return Internal stream + */ + inline Stream* ByteStream::GetStream() const { return m_context.stream; } + /*! + * \brief Flushes the stream + * \return true if flushing is successful + */ + inline bool ByteStream::FlushBits() { if (!m_context.stream) @@ -59,6 +101,14 @@ namespace Nz return true; } + /*! + * \brief Reads data + * \return Number of data read + * + * \param buffer Preallocated buffer to contain information read + * \param size Size of the read and thus of the buffer + */ + inline std::size_t ByteStream::Read(void* ptr, std::size_t size) { if (!m_context.stream) @@ -68,13 +118,29 @@ namespace Nz return m_context.stream->Read(ptr, size); } + /*! + * \brief Sets the stream endianness + * + * \param Type of the endianness + */ + inline void ByteStream::SetDataEndianness(Endianness endiannes) { m_context.endianness = endiannes; } + /*! + * \brief Sets this with a stream + * + * \param stream Stream existing + * + * \remark Produces a NazaraAssert if stream is invalid + */ + inline void ByteStream::SetStream(Stream* stream) { + NazaraAssert(stream, "Invalid stream"); + // We don't want to lose some bits.. FlushBits(); @@ -82,6 +148,16 @@ namespace Nz m_ownedStream.reset(); } + /*! + * \brief Writes data + * \return Number of data 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 + */ + inline void ByteStream::Write(const void* data, std::size_t size) { if (!m_context.stream) @@ -91,6 +167,15 @@ namespace Nz m_context.stream->Write(data, size); } + /*! + * \brief Outputs a data from the stream + * \return A reference to this + * + * \param value Value to unserialize + * + * \remark Produces a NazaraError if unserialization failed + */ + template ByteStream& ByteStream::operator>>(T& value) { @@ -103,6 +188,15 @@ namespace Nz return *this; } + /*! + * \brief Adds the data to the stream + * \return A reference to this + * + * \param value Value to serialize + * + * \remark Produces a NazaraError if serialization failed + */ + template ByteStream& ByteStream::operator<<(const T& value) { @@ -115,6 +209,13 @@ namespace Nz return *this; } + /*! + * \brief Moves the other byte stream into this + * \return A reference to this + * + * \param stream ByteStream to move in this + */ + inline ByteStream& ByteStream::operator=(ByteStream&& stream) { m_context = stream.m_context; diff --git a/include/Nazara/Core/CallOnExit.inl b/include/Nazara/Core/CallOnExit.inl index f89810a77..987da852e 100644 --- a/include/Nazara/Core/CallOnExit.inl +++ b/include/Nazara/Core/CallOnExit.inl @@ -7,17 +7,38 @@ namespace Nz { + /*! + * \class Nz::CallOnExit + * \brief Core class that represents a function to call at the end of the scope + */ + + /*! + * \brief Constructs a CallOnExit object with a function + * + * \param func Function to call on exit + */ + inline CallOnExit::CallOnExit(Func func) : m_func(func) { } + /*! + * \brief Destructs the object and calls the function + */ + inline CallOnExit::~CallOnExit() { if (m_func) m_func(); } + /*! + * \brief Calls the function and sets the new callback + * + * \param func Function to call on exit + */ + inline void CallOnExit::CallAndReset(Func func) { if (m_func) @@ -26,6 +47,12 @@ namespace Nz Reset(func); } + /*! + * \brief Resets the function + * + * \param func Function to call on exit + */ + inline void CallOnExit::Reset(Func func) { m_func = func; diff --git a/include/Nazara/Core/Color.inl b/include/Nazara/Core/Color.inl index ac576eee3..7dcfc7d75 100644 --- a/include/Nazara/Core/Color.inl +++ b/include/Nazara/Core/Color.inl @@ -11,10 +11,28 @@ namespace Nz { + /*! + * \class Nz::Color + * \brief Core class that represents a color + */ + + /*! + * \brief Constructs a Color object by default + */ + inline Color::Color() { } + /*! + * \brief Constructs a Color object with values + * + * \param red Red value + * \param green Green value + * \param blue Blue value + * \param alpha Alpha value + */ + inline Color::Color(UInt8 red, UInt8 green, UInt8 blue, UInt8 alpha) : r(red), g(green), @@ -23,6 +41,12 @@ namespace Nz { } + /*! + * \brief Constructs a Color object with a light level + * + * \param lightness Value for r, g and b + */ + inline Color::Color(UInt8 lightness) : r(lightness), g(lightness), @@ -31,6 +55,13 @@ namespace Nz { } + /*! + * \brief Constructs a Color object with values + * + * \param vec[3] vec[0] = red value, vec[1] = green value, vec[2] = blue value + * \param alpha Alpha value + */ + inline Color::Color(UInt8 vec[3], UInt8 alpha) : r(vec[0]), g(vec[1]), @@ -39,6 +70,11 @@ namespace Nz { } + /*! + * \brief Converts this to string + * \return String representation of the object "Color(r, g, b[, a])" + */ + inline String Color::ToString() const { StringStream ss; @@ -52,6 +88,13 @@ namespace Nz return ss; } + /*! + * \brief Adds two colors together + * \return Color which is the sum + * + * \param color Other color + */ + inline Color Color::operator+(const Color& color) const { ///TODO: Improve this shit @@ -64,6 +107,13 @@ namespace Nz return c; } + /*! + * \brief Multiplies two colors together + * \return Color which is the product + * + * \param color Other color + */ + inline Color Color::operator*(const Color& color) const { ///TODO: Improve this shit @@ -76,48 +126,104 @@ namespace Nz return c; } + /*! + * \brief Adds the color to this + * \return Color which is the sum + * + * \param color Other color + */ + inline Color Color::operator+=(const Color& color) { return operator=(operator+(color)); } + /*! + * \brief Multiplies the color to this + * \return Color which is the product + * + * \param color Other color + */ + inline Color Color::operator*=(const Color& color) { return operator=(operator*(color)); } + /*! + * \brief Checks whether the two colors are equal + * \return true if it is the case + * + * \param color Color to compare + */ + inline bool Color::operator==(const Color& color) const { return r == color.r && g == color.g && b == color.b && a == color.a; } + /*! + * \brief Checks whether the two colors are equal + * \return false if it is the case + * + * \param color Color to compare + */ + inline bool Color::operator!=(const Color& color) const { return !operator==(color); } - // Algorithmes venant de http://www.easyrgb.com/index.php?X=MATH + // Algorithm coming from http://www.easyrgb.com/index.php?X=MATH + + /*! + * \brief Converts CMY representation to RGB + * \return Color resulting + * + * \param cyan Cyan component + * \param magenta Magenta component + * \param yellow Yellow component + */ inline Color Color::FromCMY(float cyan, float magenta, float yellow) { return Color(static_cast((1.f-cyan)*255.f), static_cast((1.f-magenta)*255.f), static_cast((1.f-yellow)*255.f)); } + /*! + * \brief Converts CMYK representation to RGB + * \return Color resulting + * + * \param cyan Cyan component + * \param magenta Magenta component + * \param yellow Yellow component + * \param black Black component + */ + inline Color Color::FromCMYK(float cyan, float magenta, float yellow, float black) { return FromCMY(cyan * (1.f - black) + black, - magenta * (1.f - black) + black, - yellow * (1.f - black) + black); + magenta * (1.f - black) + black, + yellow * (1.f - black) + black); } + /*! + * \brief Converts HSL representation to RGB + * \return Color resulting + * + * \param hue Hue component + * \param saturation Saturation component + * \param lightness Lightness component + */ + inline Color Color::FromHSL(UInt8 hue, UInt8 saturation, UInt8 lightness) { if (saturation == 0) { // RGB results from 0 to 255 return Color(lightness * 255, - lightness * 255, - lightness * 255); + lightness * 255, + lightness * 255); } else { @@ -135,11 +241,20 @@ namespace Nz float v1 = 2.f * l - v2; return Color(static_cast(255.f * Hue2RGB(v1, v2, h + (1.f/3.f))), - static_cast(255.f * Hue2RGB(v1, v2, h)), - static_cast(255.f * Hue2RGB(v1, v2, h - (1.f/3.f)))); + static_cast(255.f * Hue2RGB(v1, v2, h)), + static_cast(255.f * Hue2RGB(v1, v2, h - (1.f/3.f)))); } } + /*! + * \brief Converts HSV representation to RGB + * \return Color resulting + * + * \param hue Hue component + * \param saturation Saturation component + * \param value Value component + */ + inline Color Color::FromHSV(float hue, float saturation, float value) { if (NumberEquals(saturation, 0.f)) @@ -201,11 +316,28 @@ namespace Nz return Color(static_cast(r*255.f), static_cast(g*255.f), static_cast(b*255.f)); } } + + /*! + * \brief Converts XYZ representation to RGB + * \return Color resulting + * + * \param vec Vector3 representing the space color + */ + inline Color Color::FromXYZ(const Vector3f& vec) { return FromXYZ(vec.x, vec.y, vec.z); } + /*! + * \brief Converts XYZ representation to RGB + * \return Color resulting + * + * \param x X component + * \param y Y component + * \param z Z component + */ + inline Color Color::FromXYZ(float x, float y, float z) { x /= 100.f; // X from 0 to 95.047 @@ -234,6 +366,15 @@ namespace Nz return Color(static_cast(r * 255.f), static_cast(g * 255.f), static_cast(b * 255.f)); } + /*! + * \brief Converts RGB representation to CMYK + * + * \param color Color to transform + * \param cyan Cyan component + * \param magenta Magenta component + * \param yellow Yellow component + */ + inline void Color::ToCMY(const Color& color, float* cyan, float* magenta, float* yellow) { *cyan = 1.f - color.r/255.f; @@ -241,6 +382,15 @@ namespace Nz *yellow = 1.f - color.b/255.f; } + /*! + * \brief Converts RGB representation to CMYK + * + * \param color Color to transform + * \param cyan Cyan component + * \param magenta Magenta component + * \param yellow Yellow component + */ + inline void Color::ToCMYK(const Color& color, float* cyan, float* magenta, float* yellow, float* black) { float c, m, y; @@ -265,6 +415,15 @@ namespace Nz *black = k; } + /*! + * \brief Converts RGB representation to HSL + * + * \param color Color to transform + * \param hue Hue component + * \param saturation Saturation component + * \param lightness Lightness component + */ + inline void Color::ToHSL(const Color& color, UInt8* hue, UInt8* saturation, UInt8* lightness) { float r = color.r / 255.f; @@ -315,6 +474,15 @@ namespace Nz } } + /*! + * \brief Converts RGB representation to HSV + * + * \param color Color to transform + * \param hue Hue component + * \param saturation Saturation component + * \param value Value component + */ + inline void Color::ToHSV(const Color& color, float* hue, float* saturation, float* value) { float r = color.r / 255.f; @@ -361,11 +529,27 @@ namespace Nz } } + /*! + * \brief Converts RGB representation to XYZ + * + * \param color Color to transform + * \param vec Vector3 representing the space color + */ + inline void Color::ToXYZ(const Color& color, Vector3f* vec) { return ToXYZ(color, &vec->x, &vec->y, &vec->z); } + /*! + * \brief Converts RGB representation to XYZ + * + * \param color Color to transform + * \param x X component + * \param y Y component + * \param z Z component + */ + inline void Color::ToXYZ(const Color& color, float* x, float* y, float* z) { float r = color.r/255.f; //R from 0 to 255 @@ -397,6 +581,15 @@ namespace Nz *z = r*0.0193f + g*0.1192f + b*0.9505f; } + /*! + * \brief Converts HUE representation to RGV + * \return RGB corresponding + * + * \param v1 V1 component + * \param v2 V2 component + * \param vH VH component + */ + inline float Color::Hue2RGB(float v1, float v2, float vH) { if (vH < 0.f) @@ -415,8 +608,16 @@ namespace Nz return v1 + (v2 - v1)*(2.f/3.f - vH)*6; return v1; + } } -} + +/*! +* \brief Output operator +* \return The stream +* +* \param out The stream +* \param color The color to output +*/ inline std::ostream& operator<<(std::ostream& out, const Nz::Color& color) { diff --git a/include/Nazara/Core/Config.hpp b/include/Nazara/Core/Config.hpp index eee521307..bd67daec6 100644 --- a/include/Nazara/Core/Config.hpp +++ b/include/Nazara/Core/Config.hpp @@ -27,36 +27,36 @@ #ifndef NAZARA_CONFIG_CORE_HPP #define NAZARA_CONFIG_CORE_HPP -/// Chaque modification d'un paramètre du module nécessite une recompilation de celui-ci +/// Each modification of a parameter needs a recompilation of the module -// Précision des réels lors de la transformation en chaîne de caractère (Max. chiffres après la virgule) +// Precision of reals when transformed into string (Max. numbers after the coma) #define NAZARA_CORE_DECIMAL_DIGITS 6 -// Duplique la sortie du log sur le flux de sortie standard (cout) +// Duplicate the log output on the standard output flux (cout) #define NAZARA_CORE_DUPLICATE_LOG_TO_COUT 0 -// Teste les assertions +// Checks the assertions #define NAZARA_CORE_ENABLE_ASSERTS 0 -// Appelle exit dès qu'une assertion est invalide +// Call exit when an assertion is invalid #define NAZARA_CORE_EXIT_ON_ASSERT_FAILURE 1 -// Taille du buffer lors d'une lecture complète d'un fichier (ex: Hash) +// Size of buffer when reading entirely a file (ex: Hash) #define NAZARA_CORE_FILE_BUFFERSIZE 4096 -// Incorpore la table Unicode Character Data (Nécessaires pour faire fonctionner le flag String::HandleUTF8) +// Incorporate the Unicode Character Data table (Necessary to make it work with the flag String::HandleUTF8) #define NAZARA_CORE_INCLUDE_UNICODEDATA 0 -// Utilise le MemoryManager pour gérer les allocations dynamiques (détecte les leaks au prix d'allocations/libérations dynamiques plus lentes) +// Use the MemoryManager to manage dynamic allocations (can detect memory leak but allocations/frees are slower) #define NAZARA_CORE_MANAGE_MEMORY 0 -// Active les tests de sécurité basés sur le code (Conseillé pour le développement) +// Activate the security tests based on the code (Advised for development) #define NAZARA_CORE_SAFE 1 -// Protège les classes des accès concurrentiels +// Protect the classes against data race #define NAZARA_CORE_THREADSAFE 1 -// Les classes à protéger des accès concurrentiels +// Classes to protect against data race #define NAZARA_THREADSAFETY_CLOCK 0 // Clock #define NAZARA_THREADSAFETY_DIRECTORY 1 // Directory #define NAZARA_THREADSAFETY_DYNLIB 1 // DynLib @@ -64,18 +64,19 @@ #define NAZARA_THREADSAFETY_LOG 1 // Log #define NAZARA_THREADSAFETY_REFCOUNTED 1 // RefCounted -// Le nombre de spinlocks à utiliser avec les sections critiques de Windows (0 pour désactiver) +// Number of spinlocks to use with the Windows critical sections (0 to disable) #define NAZARA_CORE_WINDOWS_CS_SPINLOCKS 4096 -// Optimise l'implémentation Windows avec certaines avancées de Windows vista (Casse la compatibilité XP) +// Optimize the Windows implementation with technologies of Windows vista (and greather) (Break the compatibility with XP) #define NAZARA_CORE_WINDOWS_VISTA 0 + /* -// Règle le temps entre le réveil du thread des timers et l'activation d'un timer (En millisecondes) +// Sets the time between waking thread timers and activating a timer (in milliseconds) #define NAZARA_CORE_TIMER_WAKEUPTIME 10 */ -/// Vérification des valeurs et types de certaines constantes +/// Checking the values and types of certain constants #include #if defined(NAZARA_STATIC) diff --git a/include/Nazara/Core/ConfigCheck.hpp b/include/Nazara/Core/ConfigCheck.hpp index 310567eef..8329f4ff0 100644 --- a/include/Nazara/Core/ConfigCheck.hpp +++ b/include/Nazara/Core/ConfigCheck.hpp @@ -7,12 +7,12 @@ #ifndef NAZARA_CONFIG_CHECK_CORE_HPP #define NAZARA_CONFIG_CHECK_CORE_HPP -/// Ce fichier sert à vérifier la valeur des constantes du fichier Config.hpp +/// This file is used to check the constant values defined in Config.hpp #include #define NazaraCheckTypeAndVal(name, type, op, val, err) static_assert(std::is_ ##type ::value && name op val, #type err) -// On force la valeur de MANAGE_MEMORY en mode debug +// We fore the value of MANAGE_MEMORY in debug #if defined(NAZARA_DEBUG) && !NAZARA_CORE_MANAGE_MEMORY #undef NAZARA_CORE_MANAGE_MEMORY #define NAZARA_CORE_MANAGE_MEMORY 0 diff --git a/include/Nazara/Core/DebugOff.hpp b/include/Nazara/Core/DebugOff.hpp index e042eff24..62788ee15 100644 --- a/include/Nazara/Core/DebugOff.hpp +++ b/include/Nazara/Core/DebugOff.hpp @@ -2,7 +2,7 @@ // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp -// On suppose que Debug.hpp a déjà été inclus, tout comme Config.hpp +// We assume that Debug.hpp has already been included, same thing for Config.hpp #if NAZARA_CORE_MANAGE_MEMORY #undef delete #undef new diff --git a/include/Nazara/Core/DynLib.hpp b/include/Nazara/Core/DynLib.hpp index 767165fe4..4f2759e22 100644 --- a/include/Nazara/Core/DynLib.hpp +++ b/include/Nazara/Core/DynLib.hpp @@ -28,7 +28,7 @@ namespace Nz { - using DynLibFunc = int (*)(); // Type "générique" de pointeur sur fonction + using DynLibFunc = int (*)(); // "Generic" type of poiter to function class DynLibImpl; @@ -56,7 +56,7 @@ namespace Nz mutable String m_lastError; DynLibImpl* m_impl; -}; + }; } #endif // NAZARA_DYNLIB_HPP diff --git a/include/Nazara/Core/Endianness.hpp b/include/Nazara/Core/Endianness.hpp index 62cac093d..44a4e9f26 100644 --- a/include/Nazara/Core/Endianness.hpp +++ b/include/Nazara/Core/Endianness.hpp @@ -11,12 +11,12 @@ #include #if !defined(NAZARA_BIG_ENDIAN) && !defined(NAZARA_LITTLE_ENDIAN) - // Détection automatique selon les macros du compilateur + // Automatic detection following macroes of compiler #if defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || (defined(__MIPS__) && defined(__MISPEB__)) || \ defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) || defined(__sparc__) || defined(__hppa__) #define NAZARA_BIG_ENDIAN #elif defined(__i386__) || defined(__i386) || defined(__X86__) || defined (__x86_64) || defined(_M_I86) || \ - defined(_M_IX86) || defined(_M_X64) + defined(_M_IX86) || defined(_M_X64) #define NAZARA_LITTLE_ENDIAN #else #error Failed to identify endianness, you must define either NAZARA_BIG_ENDIAN or NAZARA_LITTLE_ENDIAN diff --git a/include/Nazara/Core/Endianness.inl b/include/Nazara/Core/Endianness.inl index 96e4fdf8a..72cb9fc43 100644 --- a/include/Nazara/Core/Endianness.inl +++ b/include/Nazara/Core/Endianness.inl @@ -7,6 +7,11 @@ namespace Nz { + /*! + * \brief Gets the platform endianness + * \return Type of the endianness + */ + inline constexpr Endianness GetPlatformEndianness() { #if defined(NAZARA_BIG_ENDIAN) @@ -16,11 +21,20 @@ namespace Nz #endif } + /*! + * \brief Swaps the byte for endianness operations + * + * \param buffer Raw memory + * \param size Size to change endianness + * + * \remark If size is greather than the preallocated buffer, the behaviour is undefined + */ + inline void SwapBytes(void* buffer, unsigned int size) { UInt8* bytes = reinterpret_cast(buffer); unsigned int i = 0; - unsigned int j = size-1; + unsigned int j = size - 1; while (i < j) std::swap(bytes[i++], bytes[j--]); diff --git a/include/Nazara/Core/Enums.hpp b/include/Nazara/Core/Enums.hpp index a261f2bd3..0c0530489 100644 --- a/include/Nazara/Core/Enums.hpp +++ b/include/Nazara/Core/Enums.hpp @@ -19,9 +19,9 @@ namespace Nz enum CursorPosition { - CursorPosition_AtBegin, // Début du fichier - CursorPosition_AtCurrent, // Position du pointeur - CursorPosition_AtEnd, // Fin du fichier + CursorPosition_AtBegin, // beginning of the file + CursorPosition_AtCurrent, // Position of the cursor + CursorPosition_AtEnd, // End of the file CursorPosition_Max = CursorPosition_AtEnd }; @@ -45,7 +45,7 @@ namespace Nz ErrorFlag_ThrowException = 0x4, ErrorFlag_ThrowExceptionDisabled = 0x8, - ErrorFlag_Max = ErrorFlag_ThrowExceptionDisabled*2-1 + ErrorFlag_Max = ErrorFlag_ThrowExceptionDisabled * 2 - 1 }; enum ErrorType @@ -75,18 +75,18 @@ namespace Nz enum OpenModeFlags { - OpenMode_NotOpen = 0x00, // Utilise le mode d'ouverture actuel + OpenMode_NotOpen = 0x00, // Use the current mod of opening - OpenMode_Append = 0x01, // Empêche l'écriture sur la partie déjà existante et met le curseur à la fin - OpenMode_Lock = 0x02, // Empêche le fichier d'être modifié tant qu'il est ouvert - OpenMode_ReadOnly = 0x04, // Ouvre uniquement en lecture - OpenMode_Text = 0x10, // Ouvre en mode texte - OpenMode_Truncate = 0x20, // Créé le fichier s'il n'existe pas et le vide s'il existe - OpenMode_WriteOnly = 0x40, // Ouvre uniquement en écriture, créé le fichier s'il n'existe pas + OpenMode_Append = 0x01, // Disable writing on existing parts and put the cursor at the end + OpenMode_Lock = 0x02, // Disable modifying the file before it is open + OpenMode_ReadOnly = 0x04, // Open in read only + OpenMode_Text = 0x10, // Open in text mod + OpenMode_Truncate = 0x20, // Create the file if it doesn't exist and empty it if it exists + OpenMode_WriteOnly = 0x40, // Open in write only, create the file if it doesn't exist - OpenMode_ReadWrite = OpenMode_ReadOnly | OpenMode_WriteOnly, // Ouvre en lecture/écriture + OpenMode_ReadWrite = OpenMode_ReadOnly | OpenMode_WriteOnly, // Open in read and write - OpenMode_Max = OpenMode_WriteOnly*2 - 1 + OpenMode_Max = OpenMode_WriteOnly * 2 - 1 }; enum ParameterType @@ -177,7 +177,7 @@ namespace Nz StreamOption_Sequential = 0x1, StreamOption_Text = 0x2, - StreamOption_Max = StreamOption_Text*2 - 1 + StreamOption_Max = StreamOption_Text * 2 - 1 }; enum Ternary diff --git a/include/Nazara/Core/File.inl b/include/Nazara/Core/File.inl index 818d0098f..ff0d148fd 100644 --- a/include/Nazara/Core/File.inl +++ b/include/Nazara/Core/File.inl @@ -8,11 +8,27 @@ namespace Nz { + /*! + * \brief Computes the hash for the file + * \return ByteArray represing the result of the hash of the file + * + * \param hash Hash to execute + * \param filePath Path for the file + */ + inline ByteArray File::ComputeHash(HashType hash, const String& filePath) { return ComputeHash(AbstractHash::Get(hash).get(), filePath); } + /*! + * \brief Computes the hash for the file + * \return ByteArray represing the result of the hash of the file + * + * \param hash Hash to execute + * \param filePath Path for the file + */ + inline ByteArray File::ComputeHash(AbstractHash* hash, const String& filePath) { return Nz::ComputeHash(hash, File(filePath)); diff --git a/include/Nazara/Core/Functor.hpp b/include/Nazara/Core/Functor.hpp index 994ecc5ae..7ce9995a7 100644 --- a/include/Nazara/Core/Functor.hpp +++ b/include/Nazara/Core/Functor.hpp @@ -9,7 +9,7 @@ #include -// Inspiré du code de la SFML par Laurent Gomila +// Inspired from the of code of the SFML by Laurent Gomila namespace Nz { diff --git a/include/Nazara/Core/Functor.inl b/include/Nazara/Core/Functor.inl index 84ea8e76f..96c22b175 100644 --- a/include/Nazara/Core/Functor.inl +++ b/include/Nazara/Core/Functor.inl @@ -6,18 +6,40 @@ namespace Nz { + /*! + * \class Nz::StdLogger + * \brief Core class that represents a functor + */ + + /*! + * \brief Constructs a FunctorWithoutArgs object with a function + * + * \param func Function to execute + */ + template FunctorWithoutArgs::FunctorWithoutArgs(F func) : m_func(func) { } + /*! + * \brief Runs the function + */ + template void FunctorWithoutArgs::Run() { m_func(); } + /*! + * \brief Constructs a FunctorWithoutArgs object with a function and its arguments + * + * \param func Function to execute + * \param args Arguments for the function + */ + template FunctorWithArgs::FunctorWithArgs(F func, Args&&... args) : m_func(func), @@ -25,12 +47,22 @@ namespace Nz { } + /*! + * \brief Runs the function + */ + template void FunctorWithArgs::Run() { Apply(m_func, m_args); } + /*! + * \brief Constructs a FunctorWithoutArgs object with a member function and an object + * + * \param func Member function to execute + * \param object Object to execute on + */ template MemberWithoutArgs::MemberWithoutArgs(void (C::*func)(), C* object) : @@ -39,6 +71,10 @@ namespace Nz { } + /*! + * \brief Runs the function + */ + template void MemberWithoutArgs::Run() { diff --git a/include/Nazara/Core/Initializer.inl b/include/Nazara/Core/Initializer.inl index cb2529643..cbf613699 100644 --- a/include/Nazara/Core/Initializer.inl +++ b/include/Nazara/Core/Initializer.inl @@ -47,6 +47,16 @@ namespace Nz }; } + /*! + * \class Nz::Initializer + * \brief Core class that represents a module initializer + */ + + /*! + * \brief Constructs a Initializer object with a boolean + * + * \param initialize Initialize the module + */ template Initializer::Initializer(bool initialize) : @@ -56,12 +66,24 @@ namespace Nz Initialize(); } + /*! + * \brief Destructs the object and call Uninitialize + * + * \see Uninitialize + */ + template Initializer::~Initializer() { Uninitialize(); } + /*! + * \brief Initialize the module + * + * \see Uninitialize + */ + template bool Initializer::Initialize() { @@ -71,12 +93,23 @@ namespace Nz return m_initialized; } + /*! + * \brief Checks whether the module is initialized + * \return true if initialized + */ + template bool Initializer::IsInitialized() const { return m_initialized; } + /*! + * \brief Uninitialize the module + * + * \see Initialize + */ + template void Initializer::Uninitialize() { @@ -84,6 +117,11 @@ namespace Nz Detail::Initializer::Uninit(); } + /*! + * \brief Converts the initializer to boolean + * \return true if initialized + */ + template Initializer::operator bool() const { diff --git a/include/Nazara/Core/MemoryHelper.inl b/include/Nazara/Core/MemoryHelper.inl index 579e02ae2..507f57bab 100644 --- a/include/Nazara/Core/MemoryHelper.inl +++ b/include/Nazara/Core/MemoryHelper.inl @@ -2,7 +2,7 @@ // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp -// Je ne suis pas fier des cinq lignes qui suivent mais difficile de faire autrement pour le moment... +// I'm not proud of those five following lines but ti's hard to do with another way now #ifdef NAZARA_DEBUG_NEWREDEFINITION_DISABLE_REDEFINITION #define NAZARA_DEBUG_NEWREDEFINITION_DISABLE_REDEFINITION_DEFINED #else @@ -16,6 +16,17 @@ namespace Nz { + /*! + * \fn Nz::MemoryHelper + * \brief Core functions that helps the handle of memory in the engine + */ + + /*! + * \brief Calls the operator delete on the pointer + * + * \remark Uses MemoryManager with NAZARA_CORE_MANAGE_MEMORY defined else operator delete + */ + inline void OperatorDelete(void* ptr) { #if NAZARA_CORE_MANAGE_MEMORY @@ -25,6 +36,12 @@ namespace Nz #endif } + /*! + * \brief Calls the operator new on the pointer + * + * \remark Uses MemoryManager with NAZARA_CORE_MANAGE_MEMORY defined else operator new + */ + inline void* OperatorNew(std::size_t size) { #if NAZARA_CORE_MANAGE_MEMORY @@ -34,6 +51,14 @@ namespace Nz #endif } + /*! + * \brief Constructs the object inplace + * \return Pointer to the constructed object + * + * \param ptr Pointer to raw memory allocated + * \param args Arguments for the constructor + */ + template T* PlacementNew(void* ptr, Args&&... args) { @@ -43,7 +68,7 @@ namespace Nz #include -// Si c'est nous qui avons défini la constante, alors il nous faut l'enlever (Pour éviter que le moteur entier n'en souffre) +// If we have defined the constant, then we have to undefine it (to avoid bloating in the engine) #ifndef NAZARA_DEBUG_NEWREDEFINITION_DISABLE_REDEFINITION_DEFINED #undef NAZARA_DEBUG_NEWREDEFINITION_DISABLE_REDEFINITION #endif diff --git a/include/Nazara/Core/MemoryPool.hpp b/include/Nazara/Core/MemoryPool.hpp index 71761b612..7aaa462bb 100644 --- a/include/Nazara/Core/MemoryPool.hpp +++ b/include/Nazara/Core/MemoryPool.hpp @@ -37,7 +37,7 @@ namespace Nz private: MemoryPool(MemoryPool* pool); - std::unique_ptr m_freeList; + std::unique_ptr m_freeList; std::unique_ptr m_pool; std::unique_ptr m_next; std::atomic_uint m_freeCount; diff --git a/include/Nazara/Core/MemoryPool.inl b/include/Nazara/Core/MemoryPool.inl index 9ba21fa0c..1f3993974 100644 --- a/include/Nazara/Core/MemoryPool.inl +++ b/include/Nazara/Core/MemoryPool.inl @@ -8,6 +8,19 @@ namespace Nz { + /*! + * \class Nz::MemoryPool + * \brief Core class that represents a memory pool + */ + + /*! + * \brief Constructs a MemoryPool object + * + * \param blockSize Size of blocks that will be allocated + * \param size Size of the pool + * \param canGrow Determine if the pool can allocate more memory + */ + inline MemoryPool::MemoryPool(unsigned int blockSize, unsigned int size, bool canGrow) : m_freeCount(size), m_previous(nullptr), @@ -16,27 +29,47 @@ namespace Nz m_size(size) { m_pool.reset(new UInt8[blockSize * size]); - m_freeList.reset(new void*[size]); + m_freeList.reset(new void* [size]); // Remplissage de la free list for (unsigned int i = 0; i < size; ++i) m_freeList[i] = &m_pool[m_blockSize * (size-i-1)]; } + /*! + * \brief Constructs a MemoryPool object by move semantic + * + * \param pool MemoryPool to move into this + */ + inline MemoryPool::MemoryPool(MemoryPool&& pool) noexcept { operator=(std::move(pool)); } + /*! + * \brief Constructs a MemoryPool object by chaining memory pool + * + * \param pool Previous MemoryPool + */ + inline MemoryPool::MemoryPool(MemoryPool* pool) : MemoryPool(pool->m_blockSize, pool->m_size, pool->m_canGrow) { m_previous = pool; } + /*! + * \brief Allocates enough memory for the size and returns a pointer to it + * \return A pointer to memory allocated + * + * \param size Size to allocate + * + * \remark If the size is greather than the blockSize of pool, new operator is called + */ + inline void* MemoryPool::Allocate(unsigned int size) { - ///DOC: Si la taille est supérieure à celle d'un bloc du pool, l'opérateur new est utilisé if (size <= m_blockSize) { if (m_freeCount > 0) @@ -53,10 +86,17 @@ namespace Nz return OperatorNew(size); } + /*! + * \brief Deletes the memory represented by the poiner + * + * Calls the destructor of the object before releasing it + * + * \remark If ptr is null, nothing is done + */ + template inline void MemoryPool::Delete(T* ptr) { - ///DOC: Va appeler le destructeur de l'objet avant de le libérer if (ptr) { ptr->~T(); @@ -64,12 +104,20 @@ namespace Nz } } + /*! + * \brief Frees the memory represented by the poiner + * + * If the pool gets empty after the call and we are the child of another pool, we commit suicide. If the pointer does not own to a block of the pool, operator delete is called + * + * \remark Throws a std::runtime_error if pointer does not point to an element of the pool with NAZARA_CORE_SAFE defined + * \remark If ptr is null, nothing is done + */ + inline void MemoryPool::Free(void* ptr) { - ///DOC: Si appelé avec un pointeur ne faisant pas partie du pool, l'opérateur delete est utilisé if (ptr) { - // Le pointeur nous appartient-il ? + // Does the pointer belong to us ? UInt8* freePtr = static_cast(ptr); UInt8* poolPtr = m_pool.get(); if (freePtr >= poolPtr && freePtr < poolPtr + m_blockSize*m_size) @@ -81,7 +129,7 @@ namespace Nz m_freeList[m_freeCount++] = ptr; - // Si nous sommes vide et l'extension d'un autre pool, nous nous suicidons + // If we are empty and the extension of another pool, we commit suicide if (m_freeCount == m_size && m_previous && !m_next) { m_previous->m_next.release(); @@ -98,31 +146,61 @@ namespace Nz } } + /*! + * \brief Gets the block size + * \return Size of the blocks + */ + inline unsigned int MemoryPool::GetBlockSize() const { return m_blockSize; } + /*! + * \brief Gets the number of free blocks + * \return Number of free blocks in the pool + */ + inline unsigned int MemoryPool::GetFreeBlocks() const { return m_freeCount; } + /*! + * \brief Gets the pool size + * \return Size of the pool + */ + inline unsigned int MemoryPool::GetSize() const { return m_size; } + /*! + * \brief Creates a new value of type T with arguments + * \return Pointer to the allocated object + * + * \param args Arguments for the new object + * + * \remark Constructs inplace in the pool + */ + template inline T* MemoryPool::New(Args&&... args) { - ///DOC: Permet de construire un objet directement dans le pook T* object = static_cast(Allocate(sizeof(T))); PlacementNew(object, std::forward(args)...); return object; } + /*! + * \brief Assigns the content of another pool by move semantic + * \return A reference to this + * + * \param pool Other pool to move into this + */ + inline MemoryPool& MemoryPool::operator=(MemoryPool&& pool) noexcept { m_blockSize = pool.m_blockSize; @@ -134,7 +212,7 @@ namespace Nz m_next = std::move(pool.m_next); m_size = pool.m_size; - // Si nous avons été créés par un autre pool, nous devons le faire pointer vers nous de nouveau + // If we have been created by another pool, we must make it point to us again if (m_previous) { m_previous->m_next.release(); diff --git a/include/Nazara/Core/MemoryStream.inl b/include/Nazara/Core/MemoryStream.inl index 73514dcc4..839f2564c 100644 --- a/include/Nazara/Core/MemoryStream.inl +++ b/include/Nazara/Core/MemoryStream.inl @@ -7,18 +7,36 @@ namespace Nz { + /*! + * \brief Constructs a MemoryStream object by default + */ + inline MemoryStream::MemoryStream() : Stream(StreamOption_None, OpenMode_ReadWrite), m_pos(0) { } + /*! + * \brief Constructs a MemoryStream object with a byte array + * + * \param byteArray Bytes to stream + * \param openMode Reading/writing mode for the stream + */ + inline MemoryStream::MemoryStream(ByteArray* byteArray, UInt32 openMode) : MemoryStream() { SetBuffer(byteArray, openMode); } + /*! + * \brief Gets the internal buffer + * \return Buffer of bytes + * + * \remark Produces a NazaraAssert if buffer is invalid + */ + inline ByteArray& MemoryStream::GetBuffer() { NazaraAssert(m_buffer, "Invalid buffer"); @@ -26,6 +44,13 @@ namespace Nz return *m_buffer; } + /*! + * \brief Gets the internal buffer + * \return Buffer of bytes + * + * \remark Produces a NazaraAssert if buffer is invalid + */ + inline const ByteArray& MemoryStream::GetBuffer() const { NazaraAssert(m_buffer, "Invalid buffer"); diff --git a/include/Nazara/Core/ObjectLibrary.inl b/include/Nazara/Core/ObjectLibrary.inl index 998adece4..41497a808 100644 --- a/include/Nazara/Core/ObjectLibrary.inl +++ b/include/Nazara/Core/ObjectLibrary.inl @@ -7,6 +7,20 @@ namespace Nz { + /*! + * \class Nz::ObjectRef + * \brief Core class that represents a reference to an object + */ + + /*! + * \brief Gets the ObjectRef object by name + * \return Optional reference + * + * \param name Name of the object + * + * \remark Produces a NazaraError if object not found + */ + template ObjectRef ObjectLibrary::Get(const String& name) { @@ -17,18 +31,37 @@ namespace Nz return ref; } + /*! + * \brief Checks whether the library has the object with that name + * \return true if it the case + */ + template bool ObjectLibrary::Has(const String& name) { return Type::s_library.find(name) != Type::s_library.end(); } + /*! + * \brief Registers the ObjectRef object with that name + * + * \param name Name of the object + * \param object Object to stock + */ + template void ObjectLibrary::Register(const String& name, ObjectRef object) { Type::s_library.emplace(name, object); } + /*! + * \brief Gets the ObjectRef object by name + * \return Optional reference + * + * \param name Name of the object + */ + template ObjectRef ObjectLibrary::Query(const String& name) { @@ -39,6 +72,12 @@ namespace Nz return nullptr; } + /*! + * \brief Unregisters the ObjectRef object with that name + * + * \param name Name of the object + */ + template void ObjectLibrary::Unregister(const String& name) { diff --git a/include/Nazara/Core/ObjectRef.inl b/include/Nazara/Core/ObjectRef.inl index 1337f0c39..7799b6cbd 100644 --- a/include/Nazara/Core/ObjectRef.inl +++ b/include/Nazara/Core/ObjectRef.inl @@ -7,12 +7,27 @@ namespace Nz { + /*! + * \class Nz::ObjectRef + * \brief Core class that represents a reference to an object + */ + + /*! + * \brief Constructs a ObjectRef object by default + */ + template ObjectRef::ObjectRef() : m_object(nullptr) { } + /*! + * \brief Constructs a ObjectRef object with a pointer to an object + * + * \param object Pointer to handle like a reference (can be nullptr) + */ + template ObjectRef::ObjectRef(T* object) : m_object(object) @@ -21,6 +36,12 @@ namespace Nz m_object->AddReference(); } + /*! + * \brief Constructs a ObjectRef object by assignation + * + * \param ref ObjectRef to assign into this + */ + template ObjectRef::ObjectRef(const ObjectRef& ref) : m_object(ref.m_object) @@ -29,6 +50,12 @@ namespace Nz m_object->AddReference(); } + /*! + * \brief Constructs a ObjectRef object from another type of ObjectRef + * + * \param ref ObjectRef of type U to convert to type T + */ + template template ObjectRef::ObjectRef(const ObjectRef& ref) : @@ -36,13 +63,23 @@ namespace Nz { } + /*! + * \brief Constructs a ObjectRef object by move semantic + * + * \param ref ObjectRef to move into this + */ + template ObjectRef::ObjectRef(ObjectRef&& ref) noexcept : m_object(ref.m_object) { - ref.m_object = nullptr; // On vole la référence + ref.m_object = nullptr; // We steal the reference } + /*! + * \brief Destructs the object (remove a reference to the object when shared) + */ + template ObjectRef::~ObjectRef() { @@ -50,27 +87,50 @@ namespace Nz m_object->RemoveReference(); } + /*! + * \brief Gets the underlying pointer + * \return Underlying pointer + */ + template T* ObjectRef::Get() const { return m_object; } + /*! + * \brief Checks whether the reference is valid + * \return true if reference is not nullptr + */ + template bool ObjectRef::IsValid() const { return m_object != nullptr; } + /*! + * \brief Releases the handle of the pointer + * \return Underlying pointer + */ + template T* ObjectRef::Release() { + if (m_object) + m_object->RemoveReference(); + T* object = m_object; m_object = nullptr; return object; } + /*! + * \brief Resets the content of the ObjectRef with another pointer + * \return true if old handle is destroyed + */ + template bool ObjectRef::Reset(T* object) { @@ -88,6 +148,13 @@ namespace Nz return destroyed; } + /*! + * \brief Swaps the content of the two ObjectRef + * \return A reference to this + * + * \param ref ObjectRef to swap + */ + template ObjectRef& ObjectRef::Swap(ObjectRef& ref) { @@ -96,24 +163,48 @@ namespace Nz return *this; } + /*! + * \brief Converts the ObjectRef to bool + * \return true if reference is not nullptr + * + * \see IsValid + */ + template ObjectRef::operator bool() const { return IsValid(); } + /*! + * \brief Dereferences the ObjectRef + * \return Underlying pointer + */ + template ObjectRef::operator T*() const { return m_object; } + /*! + * \brief Dereferences the ObjectRef + * \return Underlying pointer + */ + template T* ObjectRef::operator->() const { return m_object; } + /*! + * \brief Assigns the object into this + * \return A reference to this + * + * \param object Pointer to handle like a reference (can be nullptr) + */ + template ObjectRef& ObjectRef::operator=(T* object) { @@ -122,6 +213,13 @@ namespace Nz return *this; } + /*! + * \brief Sets the reference of the ObjectRef with the handle from another + * \return A reference to this + * + * \param ref The other ObjectRef + */ + template ObjectRef& ObjectRef::operator=(const ObjectRef& ref) { @@ -130,6 +228,13 @@ namespace Nz return *this; } + /*! + * \brief Sets the reference of the ObjectRef from another type of ObjectRef + * \return A reference to this + * + * \param ref ObjectRef of type U to convert + */ + template template ObjectRef& ObjectRef::operator=(const ObjectRef& ref) @@ -141,6 +246,13 @@ namespace Nz return *this; } + /*! + * \brief Moves the ObjectRef into this + * \return A reference to this + * + * \param ref ObjectRef to move in this + */ + template ObjectRef& ObjectRef::operator=(ObjectRef&& ref) noexcept { @@ -154,6 +266,13 @@ namespace Nz namespace std { + /*! + * \brief Gives a hash representation of the object, specialisation of std + * \return Hash of the ObjectRef + * + * \param object Object to hash + */ + template struct hash> { diff --git a/include/Nazara/Core/OffsetOf.hpp b/include/Nazara/Core/OffsetOf.hpp index 7b97a44e2..d6596dcf2 100644 --- a/include/Nazara/Core/OffsetOf.hpp +++ b/include/Nazara/Core/OffsetOf.hpp @@ -7,7 +7,7 @@ #ifndef NAZARA_OFFSETOF_HPP #define NAZARA_OFFSETOF_HPP -// Par "Jesse Good" de SO: +// By "Jesse Good" from SO: // http://stackoverflow.com/questions/12811330/c-compile-time-offsetof-inside-a-template?answertab=votes#tab-top namespace Nz diff --git a/include/Nazara/Core/PluginManager.hpp b/include/Nazara/Core/PluginManager.hpp index b2b20ffde..833f0c5d2 100644 --- a/include/Nazara/Core/PluginManager.hpp +++ b/include/Nazara/Core/PluginManager.hpp @@ -13,7 +13,7 @@ #include #include -///TODO: Révision +///TODO: Revision namespace Nz { class DynLib; diff --git a/include/Nazara/Core/Primitive.inl b/include/Nazara/Core/Primitive.inl index ce458739d..8aeecc5b6 100644 --- a/include/Nazara/Core/Primitive.inl +++ b/include/Nazara/Core/Primitive.inl @@ -6,6 +6,20 @@ namespace Nz { + /*! + * \class Nz::PrimitiveList + * \brief Core class that represents a geometric primitive + */ + + /*! + * \brief Makes a box centered + * + * \param lengths (Width, Height, Depht) + * \param subdivision Number of subdivision for the axis + * \param transformMatrix Matrix to apply + * \param uvCoords Coordinates for texture + */ + inline void Primitive::MakeBox(const Vector3f& lengths, const Vector3ui& subdivision, const Matrix4f& transformMatrix, const Rectf& uvCoords) { matrix = transformMatrix; @@ -15,11 +29,31 @@ namespace Nz box.subdivision = subdivision; } + /*! + * \brief Makes 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 + * \param uvCoords Coordinates for texture + */ + inline void Primitive::MakeBox(const Vector3f& lengths, const Vector3ui& subdivision, const Vector3f& position, const Quaternionf& rotation, const Rectf& uvCoords) { MakeBox(lengths, subdivision, Matrix4f::Transform(position, rotation), uvCoords); } + /*! + * \brief Makes 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 + * \param uvCoords Coordinates for texture + */ + inline void Primitive::MakeCone(float length, float radius, unsigned int subdivision, const Matrix4f& transformMatrix, const Rectf& uvCoords) { matrix = transformMatrix; @@ -30,11 +64,31 @@ namespace Nz cone.subdivision = subdivision; } + /*! + * \brief Makes 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 + * \param uvCoords Coordinates for texture + */ + inline void Primitive::MakeCone(float length, float radius, unsigned int subdivision, const Vector3f& position, const Quaternionf& rotation, const Rectf& uvCoords) { MakeCone(length, radius, subdivision, Matrix4f::Transform(position, rotation), uvCoords); } + /*! + * \brief Makes 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 + * \param uvCoords Coordinates for texture + */ + inline void Primitive::MakeCubicSphere(float size, unsigned int subdivision, const Matrix4f& transformMatrix, const Rectf& uvCoords) { matrix = transformMatrix; @@ -45,11 +99,30 @@ namespace Nz sphere.cubic.subdivision = subdivision; } + /*! + * \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 + * \param uvCoords Coordinates for texture + */ + inline void Primitive::MakeCubicSphere(float size, unsigned int subdivision, const Vector3f& position, const Quaternionf& rotation, const Rectf& uvCoords) { MakeCubicSphere(size, subdivision, Matrix4f::Transform(position, rotation), uvCoords); } + /*! + * \brief Makes 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 + * \param uvCoords Coordinates for texture + */ + inline void Primitive::MakeIcoSphere(float size, unsigned int recursionLevel, const Matrix4f& transformMatrix, const Rectf& uvCoords) { matrix = transformMatrix; @@ -60,11 +133,30 @@ namespace Nz sphere.ico.recursionLevel = recursionLevel; } + /*! + * \brief Makes 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 + * \param uvCoords Coordinates for texture + */ + inline void Primitive::MakeIcoSphere(float size, unsigned int recursionLevel, const Vector3f& position, const Quaternionf& rotation, const Rectf& uvCoords) { MakeIcoSphere(size, recursionLevel, Matrix4f::Transform(position, rotation), uvCoords); } + /*! + * \brief Makes a plane, centered in (0, 0, 0) + * + * \param size (Width, Depth) + * \param subdivision Number of subdivision for the axis + * \param transformMatrix Matrix to apply + * \param uvCoords Coordinates for texture + */ + inline void Primitive::MakePlane(const Vector2f& size, const Vector2ui& subdivision, const Matrix4f& transformMatrix, const Rectf& uvCoords) { matrix = transformMatrix; @@ -74,16 +166,45 @@ namespace Nz plane.subdivision = subdivision; } + /*! + * \brief Makes 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 + * \param uvCoords Coordinates for texture + */ + inline void Primitive::MakePlane(const Vector2f& size, const Vector2ui& subdivision, const Planef& planeInfo, const Rectf& uvCoords) { MakePlane(size, subdivision, Matrix4f::Transform(planeInfo.distance * planeInfo.normal, Quaternionf::RotationBetween(Vector3f::Up(), planeInfo.normal)), uvCoords); } + /*! + * \brief Makes 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 + * \param uvCoords Coordinates for texture + */ + inline void Primitive::MakePlane(const Vector2f& size, const Vector2ui& subdivision, const Vector3f& position, const Quaternionf& rotation, const Rectf& uvCoords) { MakePlane(size, subdivision, Matrix4f::Transform(position, rotation), uvCoords); } + /*! + * \brief Makes 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 + * \param uvCoords Coordinates for texture + */ + inline void Primitive::MakeUVSphere(float size, unsigned int sliceCount, unsigned int stackCount, const Matrix4f& transformMatrix, const Rectf& uvCoords) { matrix = transformMatrix; @@ -95,11 +216,32 @@ namespace Nz sphere.uv.stackCount = stackCount; } + /*! + * \brief Makes 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 + * \param uvCoords Coordinates for texture + */ + inline void Primitive::MakeUVSphere(float size, unsigned int sliceCount, unsigned int stackCount, const Vector3f& position, const Quaternionf& rotation, const Rectf& uvCoords) { MakeUVSphere(size, sliceCount, stackCount, Matrix4f::Transform(position, rotation), uvCoords); } + /*! + * \brief Creates a box centered + * \return Primitive which is a box + * + * \param lengths (Width, Height, Depht) + * \param subdivision Number of subdivision for the axis + * \param transformMatrix Matrix to apply + * \param uvCoords Coordinates for texture + */ + inline Primitive Primitive::Box(const Vector3f& lengths, const Vector3ui& subdivision, const Matrix4f& transformMatrix, const Rectf& uvCoords) { Primitive primitive; @@ -108,6 +250,17 @@ namespace Nz return primitive; } + /*! + * \brief Creates a box centered + * \return Primitive which is a box + * + * \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 + * \param uvCoords Coordinates for texture + */ + inline Primitive Primitive::Box(const Vector3f& lengths, const Vector3ui& subdivision, const Vector3f& position, const Quaternionf& rotation, const Rectf& uvCoords) { Primitive primitive; @@ -116,6 +269,17 @@ namespace Nz return primitive; } + /*! + * \brief Creates a cone, centered in (0, 0, 0) and circle in (0, -length, 0) + * \return Primitive which is a cone + * + * \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 + * \param uvCoords Coordinates for texture + */ + inline Primitive Primitive::Cone(float length, float radius, unsigned int subdivision, const Matrix4f& transformMatrix, const Rectf& uvCoords) { Primitive primitive; @@ -124,6 +288,18 @@ namespace Nz return primitive; } + /*! + * \brief Creates a cone, centered in (0, 0, 0) and circle in (0, -length, 0) + * \return Primitive which is a cone + * + * \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 + * \param uvCoords Coordinates for texture + */ + inline Primitive Primitive::Cone(float length, float radius, unsigned int subdivision, const Vector3f& position, const Quaternionf& rotation, const Rectf& uvCoords) { Primitive primitive; @@ -132,6 +308,16 @@ namespace Nz return primitive; } + /*! + * \brief Creates a cubic sphere, centered in (0, 0, 0) + * \return Primitive which is a cubic sphere + * + * \param size Radius of the cubic sphere + * \param subdivision Number of subdivision for the box + * \param transformMatrix Matrix to apply + * \param uvCoords Coordinates for texture + */ + inline Primitive Primitive::CubicSphere(float size, unsigned int subdivision, const Matrix4f& transformMatrix, const Rectf& uvCoords) { Primitive primitive; @@ -140,6 +326,17 @@ namespace Nz return primitive; } + /*! + * \brief Creates a cubic sphere, centered in (0, 0, 0) + * \return Primitive which is a cubic sphere + * + * \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 + * \param uvCoords Coordinates for texture + */ + inline Primitive Primitive::CubicSphere(float size, unsigned int subdivision, const Vector3f& position, const Quaternionf& rotation, const Rectf& uvCoords) { Primitive primitive; @@ -148,6 +345,16 @@ namespace Nz return primitive; } + /*! + * \brief Creates a icosphere, centered in (0, 0, 0) + * \return Primitive which is a icosphere + * + * \param size Radius of the icosphere + * \param recursionLevel Number of recursion for the icosphere + * \param transformMatrix Matrix to apply + * \param uvCoords Coordinates for texture + */ + inline Primitive Primitive::IcoSphere(float size, unsigned int recursionLevel, const Matrix4f& transformMatrix, const Rectf& uvCoords) { Primitive primitive; @@ -156,6 +363,17 @@ namespace Nz return primitive; } + /*! + * \brief Creates a icosphere, centered in (0, 0, 0) + * \return Primitive which is a icosphere + * + * \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 + * \param uvCoords Coordinates for texture + */ + inline Primitive Primitive::IcoSphere(float size, unsigned int recursionLevel, const Vector3f& position, const Quaternionf& rotation, const Rectf& uvCoords) { Primitive primitive; @@ -164,6 +382,16 @@ namespace Nz return primitive; } + /*! + * \brief Creates a plane, centered in (0, 0, 0) + * \return Primitive which is a plane + * + * \param size (Width, Depth) + * \param subdivision Number of subdivision for the axis + * \param transformMatrix Matrix to apply + * \param uvCoords Coordinates for texture + */ + inline Primitive Primitive::Plane(const Vector2f& size, const Vector2ui& subdivision, const Matrix4f& transformMatrix, const Rectf& uvCoords) { Primitive primitive; @@ -172,6 +400,16 @@ namespace Nz return primitive; } + /*! + * \brief Creates a plane, centered in (0, 0, 0) + * \return Primitive which is a plane + * + * \param size (Width, Depth) + * \param subdivision Number of subdivision for the axis + * \param planeInfo Information for the plane + * \param uvCoords Coordinates for texture + */ + inline Primitive Primitive::Plane(const Vector2f& size, const Vector2ui& subdivision, const Planef& plane, const Rectf& uvCoords) { Primitive primitive; @@ -180,6 +418,17 @@ namespace Nz return primitive; } + /*! + * \brief Creates a plane, centered in (0, 0, 0) + * \return Primitive which is a plane + * + * \param size (Width, Depth) + * \param subdivision Number of subdivision for the axis + * \param position Position of the plane + * \param rotation Rotation of the plane + * \param uvCoords Coordinates for texture + */ + inline Primitive Primitive::Plane(const Vector2f& size, const Vector2ui& subdivision, const Vector3f& position, const Quaternionf& rotation, const Rectf& uvCoords) { Primitive primitive; @@ -188,6 +437,17 @@ namespace Nz return primitive; } + /*! + * \brief Creates a UV sphere, centered in (0, 0, 0) + * \return Primitive which is a uv sphere + * + * \param size Radius of the sphere + * \param sliceCount Number of slices + * \param stackCount Number of stacks + * \param transformMatrix Matrix to apply + * \param uvCoords Coordinates for texture + */ + inline Primitive Primitive::UVSphere(float size, unsigned int sliceCount, unsigned int stackCount, const Matrix4f& transformMatrix, const Rectf& uvCoords) { Primitive primitive; @@ -196,6 +456,18 @@ namespace Nz return primitive; } + /*! + * \brief Creates a UV sphere, centered in (0, 0, 0) + * \return Primitive which is a uv sphere + * + * \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 + * \param uvCoords Coordinates for texture + */ + inline Primitive Primitive::UVSphere(float size, unsigned int sliceCount, unsigned int stackCount, const Vector3f& position, const Quaternionf& rotation, const Rectf& uvCoords) { Primitive primitive; diff --git a/include/Nazara/Core/ResourceLoader.inl b/include/Nazara/Core/ResourceLoader.inl index e3f7c4577..e58ec1b33 100644 --- a/include/Nazara/Core/ResourceLoader.inl +++ b/include/Nazara/Core/ResourceLoader.inl @@ -11,6 +11,18 @@ namespace Nz { + /*! + * \class Nz::ResourceLoader + * \brief Core class that represents a loader of resources + */ + + /*! + * \brief Checks whether the extension of the file is supported + * \return true if supported + * + * \param extension Extension of the file + */ + template bool ResourceLoader::IsExtensionSupported(const String& extension) { @@ -25,10 +37,32 @@ namespace Nz return false; } + /*! + * \brief Loads a resource from a filepath and parameters + * \return true if successfully loaded + * + * \param resource Resource to load + * \param filePath Path to the resource + * \param parameters Parameters for the load + * + * \remark Produces a NazaraError if resource is nullptr with NAZARA_CORE_SAFE defined + * \remark Produces a NazaraError if parameters are invalid with NAZARA_CORE_SAFE defined + * \remark Produces a NazaraError if filePath has no extension + * \remark Produces a NazaraError if file count not be opened + * \remark Produces a NazaraWarning if loader failed + * \remark Produces a NazaraError if all loaders failed or no loader was found + */ + template bool ResourceLoader::LoadFromFile(Type* resource, const String& filePath, const Parameters& parameters) { #if NAZARA_CORE_SAFE + if (!resource) + { + NazaraError("Pointer invalid"); + return false; + } + if (!parameters.IsValid()) { NazaraError("Invalid parameters"); @@ -122,13 +156,29 @@ namespace Nz return false; } + /*! + * \brief Loads a resource from a raw memory, a size and parameters + * \return true if successfully loaded + * + * \param resource Resource to load + * \param data Raw memory of the resource + * \param size Size available for the read + * \param parameters Parameters for the load + * + * \remark Produces a NazaraError if resource is nullptr with NAZARA_CORE_SAFE defined + * \remark Produces a NazaraError if size is 0 with NAZARA_CORE_SAFE defined + * \remark Produces a NazaraError if parameters are invalid with NAZARA_CORE_SAFE defined + * \remark Produces a NazaraWarning if loader failed + * \remark Produces a NazaraError if all loaders failed or no loader was found + */ + template bool ResourceLoader::LoadFromMemory(Type* resource, const void* data, unsigned int size, const Parameters& parameters) { #if NAZARA_CORE_SAFE - if (!parameters.IsValid()) + if (!resource) { - NazaraError("Invalid parameters"); + NazaraError("Pointer invalid"); return false; } @@ -137,6 +187,12 @@ namespace Nz NazaraError("No data to load"); return false; } + + if (!parameters.IsValid()) + { + NazaraError("Invalid parameters"); + return false; + } #endif MemoryView stream(data, size); @@ -198,13 +254,28 @@ namespace Nz return false; } + /*! + * \brief Loads a resource from a stream and parameters + * \return true if successfully loaded + * + * \param resource Resource to load + * \param stream Stream of the resource + * \param parameters Parameters for the load + * + * \remark Produces a NazaraError if resource is nullptr with NAZARA_CORE_SAFE defined + * \remark Produces a NazaraError if stream has no data with NAZARA_CORE_SAFE defined + * \remark Produces a NazaraError if parameters are invalid with NAZARA_CORE_SAFE defined + * \remark Produces a NazaraWarning if loader failed + * \remark Produces a NazaraError if all loaders failed or no loader was found + */ + template bool ResourceLoader::LoadFromStream(Type* resource, Stream& stream, const Parameters& parameters) { #if NAZARA_CORE_SAFE - if (!parameters.IsValid()) + if (!resource) { - NazaraError("Invalid parameters"); + NazaraError("Pointer invalid"); return false; } @@ -213,6 +284,12 @@ namespace Nz NazaraError("No data to load"); return false; } + + if (!parameters.IsValid()) + { + NazaraError("Invalid parameters"); + return false; + } #endif UInt64 streamPos = stream.GetCursorPos(); @@ -224,17 +301,17 @@ namespace Nz stream.SetCursorPos(streamPos); - // Le loader supporte-t-il les données ? + // Does the loader support these data ? Ternary recognized = checkFunc(stream, parameters); if (recognized == Ternary_False) continue; else if (recognized == Ternary_True) found = true; - // On repositionne le stream à son ancienne position + // We move the stream to its old position stream.SetCursorPos(streamPos); - // Chargement de la ressource + // Load of the resource if (streamLoader(resource, stream, parameters)) return true; @@ -250,6 +327,16 @@ namespace Nz return false; } + /*! + * \brief Registers the loader + * + * \param extensionGetter A function to test whether the extension (as a string) is supported by this loader + * \param checkFunc A function to check the stream with the parser + * \param streamLoader A function to load the data from a stream in the resource + * \param fileLoader Optional function to load the data from a file in the resource + * \param memoryLoader Optional function to load the data from a raw memory in the resource + */ + template void ResourceLoader::RegisterLoader(ExtensionGetter extensionGetter, StreamChecker checkFunc, StreamLoader streamLoader, FileLoader fileLoader, MemoryLoader memoryLoader) { @@ -272,6 +359,16 @@ namespace Nz Type::s_loaders.push_front(std::make_tuple(extensionGetter, checkFunc, streamLoader, fileLoader, memoryLoader)); } + /*! + * \brief Unregisters the loader + * + * \param extensionGetter A function to test whether the extension (as a string) is supported by this loader + * \param checkFunc A function to check the stream with the parser + * \param streamLoader A function to load the data from a stream in the resource + * \param fileLoader Optional function to load the data from a file in the resource + * \param memoryLoader Optional function to load the data from a raw memory in the resource + */ + template void ResourceLoader::UnregisterLoader(ExtensionGetter extensionGetter, StreamChecker checkFunc, StreamLoader streamLoader, FileLoader fileLoader, MemoryLoader memoryLoader) { diff --git a/include/Nazara/Core/ResourceManager.inl b/include/Nazara/Core/ResourceManager.inl index c5f37237e..9c8dc903b 100644 --- a/include/Nazara/Core/ResourceManager.inl +++ b/include/Nazara/Core/ResourceManager.inl @@ -9,12 +9,28 @@ namespace Nz { + /*! + * \class Nz::ResourceManager + * \brief Core class that represents a resource manager + */ + + /*! + * \brief Clears the content of the manager + */ + template void ResourceManager::Clear() { Type::s_managerMap.clear(); } + /*! + * \brief Gets a reference to the object loaded from file + * \return Reference to the object + * + * \param filePath Path to the asset that will be loaded + */ + template ObjectRef ResourceManager::Get(const String& filePath) { @@ -43,12 +59,21 @@ namespace Nz return it->second; } + /*! + * \brief Gets the defaults parameters for the load + * \return Default parameters for loading from file + */ + template const Parameters& ResourceManager::GetDefaultParameters() { return Type::s_managerParameters; } + /*! + * \brief Purges the resource manager from every asset whose it is the only owner + */ + template void ResourceManager::Purge() { @@ -56,16 +81,23 @@ namespace Nz while (it != Type::s_managerMap.end()) { const ObjectRef& ref = it->second; - if (ref.GetReferenceCount() == 1) // Sommes-nous les seuls à détenir la ressource ? + if (ref.GetReferenceCount() == 1) // Are we the only ones to own the resource ? { NazaraDebug("Purging resource from file " + ref->GetFilePath()); - Type::s_managerMap.erase(it++); // Alors on la supprime + Type::s_managerMap.erase(it++); // Then we erase it } else ++it; } } + /*! + * \brief Registers the resource under the filePath + * + * \param filePath Path for the resource + * \param resource Object to associate with + */ + template void ResourceManager::Register(const String& filePath, ObjectRef resource) { @@ -74,12 +106,24 @@ namespace Nz Type::s_managerMap[absolutePath] = resource; } + /*! + * \brief Sets the defaults parameters for the load + * + * \param params Default parameters for loading from file + */ + template void ResourceManager::SetDefaultParameters(const Parameters& params) { Type::s_managerParameters = params; } + /*! + * \brief Unregisters the resource under the filePath + * + * \param filePath Path for the resource + */ + template void ResourceManager::Unregister(const String& filePath) { @@ -88,12 +132,21 @@ namespace Nz Type::s_managerMap.erase(absolutePath); } + /*! + * \brief Initializes the resource manager + * \return true + */ + template bool ResourceManager::Initialize() { return true; } + /*! + * \brief Uninitialize the resource manager + */ + template void ResourceManager::Uninitialize() { diff --git a/include/Nazara/Core/Signal.inl b/include/Nazara/Core/Signal.inl index a635302ec..de1609d78 100644 --- a/include/Nazara/Core/Signal.inl +++ b/include/Nazara/Core/Signal.inl @@ -8,18 +8,37 @@ namespace Nz { + /*! + * \class Nz::Signal + * \brief Core class that represents a signal, a list of objects waiting for its message + */ + + /*! + * \brief Constructs a Signal object by default + */ + template Signal::Signal() : m_slotIterator(0) { } + /*! + * \brief Constructs a Signal object by move semantic + * + * \param signal Signal to move in this + */ + template Signal::Signal(Signal&& signal) { operator=(std::move(signal)); } + /*! + * \brief Clears the list of actions attached to the signal + */ + template void Signal::Clear() { @@ -27,12 +46,26 @@ namespace Nz m_slotIterator = 0; } + /*! + * \brief Connects a function to the signal + * \return Connection attached to the signal + * + * \param func Non-member function + */ + template typename Signal::Connection Signal::Connect(const Callback& func) { return Connect(Callback(func)); } + /*! + * \brief Connects a function to the signal + * \return Connection attached to the signal + * + * \param func Non-member function + */ + template typename Signal::Connection Signal::Connect(Callback&& func) { @@ -54,6 +87,14 @@ namespace Nz return Connection(m_slots.back()); } + /*! + * \brief Connects a member function and its object to the signal + * \return Connection attached to the signal + * + * \param object Object to send the message + * \param method Member function + */ + template template typename Signal::Connection Signal::Connect(O& object, void (O::*method) (Args...)) @@ -64,6 +105,14 @@ namespace Nz }); } + /*! + * \brief Connects a member function and its object to the signal + * \return Connection attached to the signal + * + * \param object Object to send the message + * \param method Member function + */ + template template typename Signal::Connection Signal::Connect(O* object, void (O::*method)(Args...)) @@ -74,6 +123,14 @@ namespace Nz }); } + /*! + * \brief Connects a member function and its object to the signal + * \return Connection attached to the signal + * + * \param object Object to send the message + * \param method Member function + */ + template template typename Signal::Connection Signal::Connect(const O& object, void (O::*method) (Args...) const) @@ -84,6 +141,14 @@ namespace Nz }); } + /*! + * \brief Connects a member function and its object to the signal + * \return Connection attached to the signal + * + * \param object Object to send the message + * \param method Member function + */ + template template typename Signal::Connection Signal::Connect(const O* object, void (O::*method)(Args...) const) @@ -94,6 +159,12 @@ namespace Nz }); } + /*! + * \brief Applies the list of arguments to every callback functions + * + * \param args Arguments to send with the message + */ + template void Signal::operator()(Args... args) const { @@ -101,6 +172,13 @@ namespace Nz m_slots[m_slotIterator]->callback(args...); } + /*! + * \brief Moves the signal into this + * \return A reference to this + * + * \param signal Signal to move in this + */ + template Signal& Signal::operator=(Signal&& signal) { @@ -114,17 +192,28 @@ namespace Nz return *this; } + /*! + * \brief Disconnects a listener from this signal + * + * \param slot Pointer to the ith listener of the signal + * + * \remark Produces a NazaraAssert if slot is invalid (nullptr) + * \remark Produces a NazaraAssert if index of slot is invalid + * \remark Produces a NazaraAssert if slot is not attached to this signal + */ + template void Signal::Disconnect(const SlotPtr& slot) { NazaraAssert(slot, "Invalid slot pointer"); NazaraAssert(slot->index < m_slots.size(), "Invalid slot index"); + NazaraAssert(slot->signal == this, "Slot is not attached to this signal"); // "Swap this slot with the last one and pop" idiom // This will preserve slot indexes // Can we safely "remove" this slot? - if (m_slotIterator >= m_slots.size()-1 || slot->index > m_slotIterator) + if (m_slotIterator >= (m_slots.size() - 1) || slot->index > m_slotIterator) { // Yes we can SlotPtr& newSlot = m_slots[slot->index]; @@ -150,6 +239,16 @@ namespace Nz m_slots.pop_back(); } + /*! + * \class Nz::Signal::Connection + * \brief Core class that represents a connection attached to a signal + */ + + /*! + * \brief Constructs a Signal::Connection object with a slot + * + * \param slot Slot of the listener + */ template Signal::Connection::Connection(const SlotPtr& slot) : @@ -157,6 +256,13 @@ namespace Nz { } + /*! + * \brief Connects to a signal with arguments + * + * \param signal New signal to listen + * \param args Arguments for the signal + */ + template template void Signal::Connection::Connect(BaseClass& signal, ConnectArgs&&... args) @@ -164,6 +270,10 @@ namespace Nz operator=(signal.Connect(std::forward(args)...)); } + /*! + * \brief Disconnects the connection from the signal + */ + template void Signal::Connection::Disconnect() { @@ -171,12 +281,27 @@ namespace Nz ptr->signal->Disconnect(ptr); } + /*! + * \brief Checks whether the connection is still active with the signal + * \return true if signal is still active + */ + template bool Signal::Connection::IsConnected() const { return !m_ptr.expired(); } + /*! + * \class Nz::Signal::ConnectionGuard + * \brief Core class that represents a RAII for a connection attached to a signal + */ + + /*! + * \brief Constructs a Signal::ConnectionGuard object with a connection + * + * \param connection Connection for the scope + */ template Signal::ConnectionGuard::ConnectionGuard(const Connection& connection) : @@ -184,18 +309,35 @@ namespace Nz { } + /*! + * \brief Constructs a Signal::ConnectionGuard object with a connection by move semantic + * + * \param connection Connection for the scope + */ + template Signal::ConnectionGuard::ConnectionGuard(Connection&& connection) : m_connection(std::move(connection)) { } + /*! + * \brief Destructs the object and disconnects the connection + */ + template Signal::ConnectionGuard::~ConnectionGuard() { m_connection.Disconnect(); } + /*! + * \brief Connects to a signal with arguments + * + * \param signal New signal to listen + * \param args Arguments for the signal + */ + template template void Signal::ConnectionGuard::Connect(BaseClass& signal, ConnectArgs&&... args) @@ -204,24 +346,45 @@ namespace Nz m_connection.Connect(signal, std::forward(args)...); } + /*! + * \brief Disconnects the connection from the signal + */ + template void Signal::ConnectionGuard::Disconnect() { m_connection.Disconnect(); } + /*! + * \brief Gets the connection attached to the signal + * \return Connection of the signal + */ + template typename Signal::Connection& Signal::ConnectionGuard::GetConnection() { return m_connection; } + /*! + * \brief Checks whether the connection is still active with the signal + * \return true if signal is still active + */ + template bool Signal::ConnectionGuard::IsConnected() const { return m_connection.IsConnected(); } + /*! + * \brief Assigns the connection into this + * \return A reference to this + * + * \param connection Connection to assign into this + */ + template typename Signal::ConnectionGuard& Signal::ConnectionGuard::operator=(const Connection& connection) { @@ -231,6 +394,13 @@ namespace Nz return *this; } + /*! + * \brief Moves the Connection into this + * \return A reference to this + * + * \param connection Connection to move in this + */ + template typename Signal::ConnectionGuard& Signal::ConnectionGuard::operator=(Connection&& connection) { @@ -240,6 +410,13 @@ namespace Nz return *this; } + /*! + * \brief Moves the ConnectionGuard into this + * \return A reference to this + * + * \param connection ConnectionGuard to move in this + */ + template typename Signal::ConnectionGuard& Signal::ConnectionGuard::operator=(ConnectionGuard&& connection) { diff --git a/include/Nazara/Core/SparsePtr.hpp b/include/Nazara/Core/SparsePtr.hpp index 79c87ca95..6e36fcc57 100644 --- a/include/Nazara/Core/SparsePtr.hpp +++ b/include/Nazara/Core/SparsePtr.hpp @@ -7,7 +7,7 @@ #ifndef NAZARA_SPARSEPTR_HPP #define NAZARA_SPARSEPTR_HPP -///FIXME: Est-ce que SparsePtr est vraiment le meilleur nom pour cette classe ? +///FIXME: Is SparsePtr a really good name for this class ? #include #include diff --git a/include/Nazara/Core/SparsePtr.inl b/include/Nazara/Core/SparsePtr.inl index d6b227226..31e83addd 100644 --- a/include/Nazara/Core/SparsePtr.inl +++ b/include/Nazara/Core/SparsePtr.inl @@ -7,24 +7,52 @@ namespace Nz { + /*! + * \class Nz::SparsePtr + * \brief Core class that represents a pointer and the step between two elements + */ + + /*! + * \brief Constructs a SparsePtr object by default + */ + template SparsePtr::SparsePtr() { Reset(); } + /*! + * \brief Constructs a SparsePtr object with a pointer + * + * \param ptr Pointer to data + */ + template SparsePtr::SparsePtr(T* ptr) { Reset(ptr); } + /*! + * \brief Constructs a SparsePtr object with a pointer and a step + * + * \param ptr Pointer to data + * \param stride Step between two elements + */ + template SparsePtr::SparsePtr(VoidPtr ptr, int stride) { Reset(ptr, stride); } + /*! + * \brief Constructs a SparsePtr object from another type of SparsePtr + * + * \param ptr Pointer to data of type U to convert to type T + */ + template template SparsePtr::SparsePtr(const SparsePtr& ptr) @@ -32,18 +60,32 @@ namespace Nz Reset(ptr); } + /*! + * \brief Gets the original pointer + * \return Pointer to the first data + */ + template typename SparsePtr::VoidPtr SparsePtr::GetPtr() const { return m_ptr; } + /*! + * \brief Gets the stride + * \return Step between two elements + */ + template int SparsePtr::GetStride() const { return m_stride; } + /*! + * \brief Resets the SparsePtr + */ + template void SparsePtr::Reset() { @@ -51,6 +93,14 @@ namespace Nz SetStride(0); } + /*! + * \brief Resets the SparsePtr with a pointer + * + * \param ptr Pointer to data + * + * \remark stride is set to sizeof(T) + */ + template void SparsePtr::Reset(T* ptr) { @@ -58,6 +108,13 @@ namespace Nz SetStride(sizeof(T)); } + /*! + * \brief Resets the SparsePtr with a pointer and its stride + * + * \param ptr Pointer to data + * \param stride Step between two elements + */ + template void SparsePtr::Reset(VoidPtr ptr, int stride) { @@ -65,6 +122,12 @@ namespace Nz SetStride(stride); } + /*! + * \brief Resets the SparsePtr with another SparsePtr + * + * \param ptr Another sparsePtr + */ + template void SparsePtr::Reset(const SparsePtr& ptr) { @@ -72,6 +135,12 @@ namespace Nz SetStride(ptr.GetStride()); } + /*! + * \brief Resets the SparsePtr with another type of SparsePtr + * + * \param ptr Another sparsePtr + */ + template template void SparsePtr::Reset(const SparsePtr& ptr) @@ -82,94 +151,187 @@ namespace Nz SetStride(ptr.GetStride()); } + /*! + * \brief Sets the pointer + * + * \param ptr Pointer to data + */ + template void SparsePtr::SetPtr(VoidPtr ptr) { m_ptr = reinterpret_cast(ptr); } + /*! + * \brief Sets the stride + * + * \param stride Step between two elements + */ + template void SparsePtr::SetStride(int stride) { m_stride = stride; } + /*! + * \brief Converts the pointer to bool + * \return true if pointer is not nullptr + */ + template SparsePtr::operator bool() const { return m_ptr != nullptr; } + /*! + * \brief Converts the pointer to a pointer to the value + * \return The value of the pointer + */ + template SparsePtr::operator T*() const { return reinterpret_cast(m_ptr); } + /*! + * \brief Dereferences the pointer + * \return The dereferencing of the pointer + */ + template T& SparsePtr::operator*() const { return *reinterpret_cast(m_ptr); } + /*! + * \brief Dereferences the pointer + * \return The dereferencing of the pointer + */ + template T* SparsePtr::operator->() const { return reinterpret_cast(m_ptr); } + /*! + * \brief Gets the ith element of the stride pointer + * \return A reference to the ith value + * + * \param index Number of stride to do + */ + template T& SparsePtr::operator[](int index) const { - return *reinterpret_cast(m_ptr + index*m_stride); + return *reinterpret_cast(m_ptr + index * m_stride); } + /*! + * \brief Gets the SparsePtr with an offset + * \return A SparsePtr with the new stride + * + * \param count Number of stride to do + */ + template SparsePtr SparsePtr::operator+(int count) const { - return SparsePtr(m_ptr + count*m_stride, m_stride); + return SparsePtr(m_ptr + count * m_stride, m_stride); } + /*! + * \brief Gets the SparsePtr with an offset + * \return A SparsePtr with the new stride + * + * \param count Number of stride to do + */ + template SparsePtr SparsePtr::operator+(unsigned int count) const { - return SparsePtr(m_ptr + count*m_stride, m_stride); + return SparsePtr(m_ptr + count * m_stride, m_stride); } + /*! + * \brief Gets the SparsePtr with an offset + * \return A SparsePtr with the new stride + * + * \param count Number of stride to do + */ + template SparsePtr SparsePtr::operator-(int count) const { - return SparsePtr(m_ptr - count*m_stride, m_stride); + return SparsePtr(m_ptr - count * m_stride, m_stride); } + /*! + * \brief Gets the SparsePtr with an offset + * \return A SparsePtr with the new stride + * + * \param count Number of stride to do + */ + template SparsePtr SparsePtr::operator-(unsigned int count) const { - return SparsePtr(m_ptr - count*m_stride, m_stride); + return SparsePtr(m_ptr - count * m_stride, m_stride); } + /*! + * \brief Gets the difference between the two SparsePtr + * \return The difference of elements: ptr - this->ptr + * + * \param ptr Other ptr + */ + template std::ptrdiff_t SparsePtr::operator-(const SparsePtr& ptr) const { - return (m_ptr - ptr.m_ptr)/m_stride; + return (m_ptr - ptr.m_ptr) / m_stride; } + /*! + * \brief Gets the SparsePtr with an offset + * \return A reference to this pointer with the new stride + * + * \param count Number of stride to do + */ + template SparsePtr& SparsePtr::operator+=(int count) { - m_ptr += count*m_stride; + m_ptr += count * m_stride; return *this; } + /*! + * \brief Gets the SparsePtr with an offset + * \return A reference to this pointer with the new stride + * + * \param count Number of stride to do + */ + template SparsePtr& SparsePtr::operator-=(int count) { - m_ptr -= count*m_stride; + m_ptr -= count * m_stride; return *this; } + /*! + * \brief Gets the SparsePtr with the next element + * \return A reference to this pointer updated + */ + template SparsePtr& SparsePtr::operator++() { @@ -178,19 +340,29 @@ namespace Nz return *this; } + /*! + * \brief Gets the SparsePtr with the next element + * \return A SparsePtr not updated + */ + template SparsePtr SparsePtr::operator++(int) { - // On fait une copie de l'objet + // We copy the object SparsePtr tmp(*this); - // On modifie l'objet + // We modify it operator++(); - // On retourne la copie + // We return the copy return tmp; } + /*! + * \brief Gets the SparsePtr with the previous element + * \return A reference to this pointer updated + */ + template SparsePtr& SparsePtr::operator--() { @@ -198,49 +370,96 @@ namespace Nz return *this; } + /*! + * \brief Gets the SparsePtr with the previous element + * \return A SparsePtr not updated + */ + template SparsePtr SparsePtr::operator--(int) { - // On fait une copie de l'objet + // We copy the object SparsePtr tmp(*this); - // On modifie l'objet + // We modify it operator--(); - // On retourne la copie + // We return the copy return tmp; } + /*! + * \brief Compares the SparsePtr to another one + * \return true if the two SparsePtr are pointing to the same memory + * + * \param ptr Other SparsePtr to compare with + */ + template bool SparsePtr::operator==(const SparsePtr& ptr) const { return m_ptr == ptr.m_ptr; } + /*! + * \brief Compares the SparsePtr to another one + * \return false if the two SparsePtr are pointing to the same memory + * + * \param ptr Other SparsePtr to compare with + */ + template bool SparsePtr::operator!=(const SparsePtr& ptr) const { return m_ptr != ptr.m_ptr; } + /*! + * \brief Compares the SparsePtr to another one + * \return true if the first SparsePtr is pointing to memory inferior to the second one + * + * \param ptr Other SparsePtr to compare with + */ + template bool SparsePtr::operator<(const SparsePtr& ptr) const { return m_ptr < ptr.m_ptr; } + /*! + * \brief Compares the SparsePtr to another one + * \return true if the first SparsePtr is pointing to memory superior to the second one + * + * \param ptr Other SparsePtr to compare with + */ + template bool SparsePtr::operator>(const SparsePtr& ptr) const { return m_ptr > ptr.m_ptr; } + /*! + * \brief Compares the SparsePtr to another one + * \return true if the first SparsePtr is pointing to memory inferior or equal to the second one + * + * \param ptr Other SparsePtr to compare with + */ + template bool SparsePtr::operator<=(const SparsePtr& ptr) const { return m_ptr <= ptr.m_ptr; } + /*! + * \brief Compares the SparsePtr to another one + * \return true if the first SparsePtr is pointing to memory superior or equal to the second one + * + * \param ptr Other SparsePtr to compare with + */ + template bool SparsePtr::operator>=(const SparsePtr& ptr) const { diff --git a/include/Nazara/Core/Stream.inl b/include/Nazara/Core/Stream.inl index 104d5e300..fa90682b0 100644 --- a/include/Nazara/Core/Stream.inl +++ b/include/Nazara/Core/Stream.inl @@ -7,12 +7,25 @@ namespace Nz { + /*! + * \brief Constructs a Stream object with options + * + * \param streamOptions Options for the stream + * \param openMode Reading/writing mode for the stream + */ + inline Stream::Stream(UInt32 streamOptions, UInt32 openMode) : m_openMode(openMode), m_streamOptions(streamOptions) { } + /*! + * \brief Enables the text mode + * + * \param textMode Enables the mode or disables + */ + inline void Stream::EnableTextMode(bool textMode) { if (textMode) @@ -21,6 +34,12 @@ namespace Nz m_streamOptions &= ~StreamOption_Text; } + /*! + * \brief Flushes the stream + * + * \remark Produces a NazaraAssert if file is not writable + */ + inline void Stream::Flush() { NazaraAssert(IsWritable(), "Stream is not writable"); @@ -28,36 +47,77 @@ namespace Nz FlushStream(); } + /*! + * \brief Gets the open mode of the stream + * \return Reading/writing mode for the stream + */ + inline UInt32 Stream::GetOpenMode() const { return m_openMode; } + /*! + * \brief Gets the options of the stream + * \return Options of the stream + */ + inline UInt32 Stream::GetStreamOptions() const { return m_streamOptions; } + /*! + * \brief Checks whether the stream is readable + * \return true if it is the case + */ + inline bool Stream::IsReadable() const { return (m_openMode & OpenMode_ReadOnly) != 0; } + /*! + * \brief Checks whether the stream is sequential + * \return true if it is the case + */ + inline bool Stream::IsSequential() const { return (m_streamOptions & StreamOption_Sequential) != 0; } + /*! + * \brief Checks whether the stream has text mode enabled + * \return true if it is the case + */ + inline bool Stream::IsTextModeEnabled() const { return (m_streamOptions & StreamOption_Text) != 0; } + /*! + * \brief Checks whether the stream can be written + * \return true if it is the case + */ + inline bool Stream::IsWritable() const { return (m_openMode & OpenMode_WriteOnly) != 0; } + /*! + * \brief Reads the stream and puts the result in a buffer + * \return Size of the read + * + * \param buffer Buffer to stock data + * \param size Size meant to be read + * + * \remark Produces a NazaraAssert if stream is not readable + * \remark If preallocated space of buffer is less than the size, the behaviour is undefined + */ + inline std::size_t Stream::Read(void* buffer, std::size_t size) { NazaraAssert(IsReadable(), "Stream is not readable"); @@ -65,6 +125,17 @@ namespace Nz return ReadBlock(buffer, size); } + /*! + * \brief Writes in the stream the content of a buffer + * \return Size of the writing + * + * \param buffer Buffer to get data from + * \param size Size meant to be written + * + * \remark Produces a NazaraAssert if stream is not writable + * \remark If preallocated space of buffer is less than the size, the behaviour is undefined + */ + inline std::size_t Stream::Write(const void* buffer, std::size_t size) { NazaraAssert(IsWritable(), "Stream is not writable"); diff --git a/include/Nazara/Core/String.hpp b/include/Nazara/Core/String.hpp index a99326bf4..70673ae8a 100644 --- a/include/Nazara/Core/String.hpp +++ b/include/Nazara/Core/String.hpp @@ -23,11 +23,11 @@ namespace Nz public: enum Flags { - None = 0x00, // Mode par défaut - CaseInsensitive = 0x01, // Insensible à la casse - HandleUtf8 = 0x02, // Traite les octets comme une suite de caractères UTF-8 - TrimOnlyLeft = 0x04, // Trim(med), ne coupe que la partie gauche de la chaîne - TrimOnlyRight = 0x08 // Trim(med), ne coupe que la partie droite de la chaîne + None = 0x00, // Default mode + CaseInsensitive = 0x01, // Case insensitive + HandleUtf8 = 0x02, // Considers bytes as a list of UTF-8 characters + TrimOnlyLeft = 0x04, // Trim(med), only cut the left part of the string + TrimOnlyRight = 0x08 // Trim(med), only cut the right part of the string }; String(); @@ -71,7 +71,7 @@ namespace Nz std::size_t FindAny(const char* string, std::intmax_t start = 0, UInt32 flags = None) const; std::size_t FindAny(const String& string, std::intmax_t start = 0, UInt32 flags = None) const; std::size_t FindLast(char character, std::intmax_t start = -1, UInt32 flags = None) const; - std::size_t FindLast(const char *string, std::intmax_t start = -1, UInt32 flags = None) const; + std::size_t FindLast(const char* string, std::intmax_t start = -1, UInt32 flags = None) const; std::size_t FindLast(const String& string, std::intmax_t start = -1, UInt32 flags = None) const; std::size_t FindLastAny(const char* string, std::intmax_t start = -1, UInt32 flags = None) const; std::size_t FindLastAny(const String& string, std::intmax_t start = -1, UInt32 flags = None) const; diff --git a/include/Nazara/Core/String.inl b/include/Nazara/Core/String.inl index 93ff32312..40c08d315 100644 --- a/include/Nazara/Core/String.inl +++ b/include/Nazara/Core/String.inl @@ -7,22 +7,42 @@ namespace Nz { + /*! + * \brief Constructs a String object with a shared string by move semantic + * + * \param sharedString Shared string to move into this + */ + inline String::String(std::shared_ptr&& sharedString) : m_sharedString(std::move(sharedString)) { } + /*! + * \brief Releases the content to the string + */ + inline void String::ReleaseString() { m_sharedString = std::move(GetEmptyString()); } + /*! + * \brief Constructs a SharedString object by default + */ + inline String::SharedString::SharedString() : // Special case: empty string capacity(0), size(0) { } + /*! + * \brief Constructs a SharedString object with a size + * + * \param strSize Number of characters in the string + */ + inline String::SharedString::SharedString(std::size_t strSize) : capacity(strSize), size(strSize), @@ -31,6 +51,13 @@ namespace Nz string[strSize] = '\0'; } + /*! + * \brief Constructs a SharedString object with a size and a capacity + * + * \param strSize Number of characters in the string + * \param strCapacity Capacity in characters in the string + */ + inline String::SharedString::SharedString(std::size_t strSize, std::size_t strCapacity) : capacity(strCapacity), size(strSize), @@ -39,6 +66,14 @@ namespace Nz string[strSize] = '\0'; } + /*! + * \brief Appends the string to the hash + * \return true if hash is successful + * + * \param hash Hash to append data of the file + * \param string String to hash + */ + inline bool HashAppend(AbstractHash* hash, const String& string) { hash->Append(reinterpret_cast(string.GetConstBuffer()), string.GetSize()); @@ -48,6 +83,13 @@ namespace Nz namespace std { + /*! + * \brief Specialisation of std to hash + * \return Result of the hash + * + * \param str String to hash + */ + template<> struct hash { diff --git a/include/Nazara/Core/TaskScheduler.inl b/include/Nazara/Core/TaskScheduler.inl index b8b99ed47..ba64cfb1a 100644 --- a/include/Nazara/Core/TaskScheduler.inl +++ b/include/Nazara/Core/TaskScheduler.inl @@ -6,18 +6,43 @@ namespace Nz { + /*! + * \class Nz::TaskScheduler + * \brief Core class that represents a thread pool + */ + + /*! + * \brief Adds a task to the pending list + * + * \param function Task that the pool will execute + */ + template void TaskScheduler::AddTask(F function) { AddTaskFunctor(new FunctorWithoutArgs(function)); } + /*! + * \brief Adds a task to the pending list + * + * \param function Task that the pool will execute + * \param args Arguments of the function + */ + template void TaskScheduler::AddTask(F function, Args&&... args) { AddTaskFunctor(new FunctorWithArgs(function, std::forward(args)...)); } + /*! + * \brief Adds a task to the pending list + * + * \param function Task that the pool will execute + * \param object Object on which the method will be called + */ + template void TaskScheduler::AddTask(void (C::*function)(), C* object) { diff --git a/include/Nazara/Core/Thread.inl b/include/Nazara/Core/Thread.inl index d6c76522a..f3de4ae24 100644 --- a/include/Nazara/Core/Thread.inl +++ b/include/Nazara/Core/Thread.inl @@ -7,18 +7,43 @@ namespace Nz { + /*! + * \class Nz::Thread + * \brief Core class that represents a thread + */ + + /*! + * \brief Constructs a Thread object with a function + * + * \param function Task the thread will execute in parallel + */ + template Thread::Thread(F function) { CreateImpl(new FunctorWithoutArgs(function)); } + /*! + * \brief Constructs a Thread object with a function and its parameters + * + * \param function Task the thread will execute in parallel + * \param args Arguments of the function + */ + template Thread::Thread(F function, Args&&... args) { CreateImpl(new FunctorWithArgs(function, std::forward(args)...)); } + /*! + * \brief Constructs a Thread object with a member function and its object + * + * \param function Task the thread will execute in parallel + * \param object Object on which the method will be called + */ + template Thread::Thread(void (C::*function)(), C* object) { diff --git a/include/Nazara/Core/ThreadSafety.hpp b/include/Nazara/Core/ThreadSafety.hpp index 26b446ae6..5b1629b5b 100644 --- a/include/Nazara/Core/ThreadSafety.hpp +++ b/include/Nazara/Core/ThreadSafety.hpp @@ -2,12 +2,12 @@ // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp -// Pas de header guard +// No header guard #include #include -// Ces macros peuvent changer pour n'importe quel fichier qui l'utilise dans une même unité de compilation +// These macroes can change for any file which uses it in the same unit of compilation #undef NazaraLock #undef NazaraMutex #undef NazaraMutexAttrib diff --git a/include/Nazara/Core/ThreadSafetyOff.hpp b/include/Nazara/Core/ThreadSafetyOff.hpp index e6a1ce208..29c327e0d 100644 --- a/include/Nazara/Core/ThreadSafetyOff.hpp +++ b/include/Nazara/Core/ThreadSafetyOff.hpp @@ -2,9 +2,9 @@ // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp -// Pas de header guard +// No header guard -// Ces macros peuvent changer pour n'importe quel fichier qui l'utilise dans une même unité de compilation +// These macroes can change for any file which uses it in the same unit of compilation #undef NazaraLock #undef NazaraMutex #undef NazaraMutexAttrib diff --git a/include/Nazara/Core/Unicode.hpp b/include/Nazara/Core/Unicode.hpp index 631d8f8bd..a42e88e90 100644 --- a/include/Nazara/Core/Unicode.hpp +++ b/include/Nazara/Core/Unicode.hpp @@ -18,16 +18,16 @@ namespace Nz Unicode() = delete; ~Unicode() = delete; /* - Catégorie Unicode: - -Les valeurs de 0x01 à 0x80 indiquent la catégorie. - -Les valeurs de 0x100 à 0x10000 indiquent la sous-catégorie. + Unicode category: + -Values between 0x01 and 0x80 specify the category + -Values between 0x100 and 0x10000 specify the subcategory */ enum Category : UInt16 { - // Catégorie non-reconnue par Nazara + // Category not handled by Nazara Category_NoCategory = 0, - // Lettres + // Letters Category_Letter = 0x01, // L Category_Letter_Lowercase = Category_Letter | 0x0100, // Ll Category_Letter_Modifier = Category_Letter | 0x0200, // Lm @@ -35,19 +35,19 @@ namespace Nz Category_Letter_Titlecase = Category_Letter | 0x0800, // Lt Category_Letter_Uppercase = Category_Letter | 0x1000, // Lu - // Marques + // Marks Category_Mark = 0x02, // M Category_Mark_Enclosing = Category_Mark | 0x100, // Me Category_Mark_NonSpacing = Category_Mark | 0x200, // Mn Category_Mark_SpacingCombining = Category_Mark | 0x400, // Mc - // Nombres + // Numbers Category_Number = 0x04, // N Category_Number_DecimalDigit = Category_Number | 0x100, // Nd Category_Number_Letter = Category_Number | 0x200, // Nl Category_Number_Other = Category_Number | 0x400, // No - // Autres + // Others Category_Other = 0x08, // C Category_Other_Control = Category_Other | 0x0100, // Cc Category_Other_Format = Category_Other | 0x0200, // Cf @@ -65,13 +65,13 @@ namespace Nz Category_Punctuation_Open = Category_Punctuation | 0x2000, // Ps Category_Punctuation_Other = Category_Punctuation | 0x4000, // Po - // Espacements + // Spaces Category_Separator = 0x20, // Z Category_Separator_Line = Category_Separator | 0x0100, // Zl Category_Separator_Paragraph = Category_Separator | 0x0200, // Zp Category_Separator_Space = Category_Separator | 0x0400, // Zs - // Symboles + // Symbols Category_Symbol = 0x40, // S Category_Symbol_Currency = Category_Symbol | 0x0100, // Sc Category_Symbol_Math = Category_Symbol | 0x0200, // Sm diff --git a/readme.md b/readme.md index ea7595a96..90a30fda5 100644 --- a/readme.md +++ b/readme.md @@ -45,4 +45,4 @@ Links - **RafBill** and **Raakz:** Finding bugs and/or testing - **Fissal "DrFisher" Hannoun**: Helping a lot in architecture design - **Alexandre "Danman" Janniaux**: Helping making the POSIX implementation -- **Gawaboumga**: Improving the engine code by merging on GitHub +- **Youri "Gawaboumga" Hubaut**: Improving the engine code by merging on GitHub diff --git a/readme_fr.md b/readme_fr.md index bc3364350..fd0f42e7b 100644 --- a/readme_fr.md +++ b/readme_fr.md @@ -45,4 +45,4 @@ Liens - **RafBill** et **Raakz:** Recherche de bugs et/ou tests - **Fissal "DrFisher" Hannoun**: Aide et conseils lors de la conception de l'architecture du moteur - **Alexandre "Danman" Janniaux**: Aide sur l'implémentation POSIX -- **Gawaboumga**: Amélioration du code via le merging sur GitHub +- **Youri "Gawaboumga" Hubaut**: Amélioration du code via le merging sur GitHub diff --git a/src/Nazara/Core/AbstractHash.cpp b/src/Nazara/Core/AbstractHash.cpp index f0e82bb19..60f2f42cb 100644 --- a/src/Nazara/Core/AbstractHash.cpp +++ b/src/Nazara/Core/AbstractHash.cpp @@ -17,8 +17,24 @@ namespace Nz { + /*! + * \class Nz::AbstractHash + * \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::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(new HashFletcher16); + return std::make_unique(); case HashType_CRC32: - return std::unique_ptr(new HashCRC32); + return std::make_unique(); case HashType_MD5: - return std::unique_ptr(new HashMD5); + return std::make_unique(); case HashType_SHA1: - return std::unique_ptr(new HashSHA1); + return std::make_unique(); case HashType_SHA224: - return std::unique_ptr(new HashSHA224); + return std::make_unique(); case HashType_SHA256: - return std::unique_ptr(new HashSHA256); + return std::make_unique(); case HashType_SHA384: - return std::unique_ptr(new HashSHA384); + return std::make_unique(); case HashType_SHA512: - return std::unique_ptr(new HashSHA512); + return std::make_unique(); case HashType_Whirlpool: - return std::unique_ptr(new HashWhirlpool); + return std::make_unique(); } NazaraInternalError("Hash type not handled (0x" + String::Number(type, 16) + ')'); - return std::unique_ptr(); + return nullptr; } } diff --git a/src/Nazara/Core/AbstractLogger.cpp b/src/Nazara/Core/AbstractLogger.cpp index 1397d3592..06695a928 100644 --- a/src/Nazara/Core/AbstractLogger.cpp +++ b/src/Nazara/Core/AbstractLogger.cpp @@ -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 + * \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; diff --git a/src/Nazara/Core/ByteArray.cpp b/src/Nazara/Core/ByteArray.cpp index cc5734822..9763e6336 100644 --- a/src/Nazara/Core/ByteArray.cpp +++ b/src/Nazara/Core/ByteArray.cpp @@ -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(); diff --git a/src/Nazara/Core/ByteStream.cpp b/src/Nazara/Core/ByteStream.cpp index 175212b48..1b0fc853e 100644 --- a/src/Nazara/Core/ByteStream.cpp +++ b/src/Nazara/Core/ByteStream.cpp @@ -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(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(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(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"); diff --git a/src/Nazara/Core/Clock.cpp b/src/Nazara/Core/Clock.cpp index dae4c84d5..ef4689d50 100644 --- a/src/Nazara/Core/Clock.cpp +++ b/src/Nazara/Core/Clock.cpp @@ -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 diff --git a/src/Nazara/Core/ConditionVariable.cpp b/src/Nazara/Core/ConditionVariable.cpp index f893c7f82..c660c6464 100644 --- a/src/Nazara/Core/ConditionVariable.cpp +++ b/src/Nazara/Core/ConditionVariable.cpp @@ -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"); diff --git a/src/Nazara/Core/Core.cpp b/src/Nazara/Core/Core.cpp index 142ffa909..26a451512 100644 --- a/src/Nazara/Core/Core.cpp +++ b/src/Nazara/Core/Core.cpp @@ -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à initialisé + 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 initialisé + // 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(); diff --git a/src/Nazara/Core/Directory.cpp b/src/Nazara/Core/Directory.cpp index ed8ed6bd0..b076b38d7 100644 --- a/src/Nazara/Core/Directory.cpp +++ b/src/Nazara/Core/Directory.cpp @@ -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; - } + } } diff --git a/src/Nazara/Core/DynLib.cpp b/src/Nazara/Core/DynLib.cpp index 39539e7ed..3261f0959 100644 --- a/src/Nazara/Core/DynLib.cpp +++ b/src/Nazara/Core/DynLib.cpp @@ -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(); diff --git a/src/Nazara/Core/Error.cpp b/src/Nazara/Core/Error.cpp index 805e60190..59a8b72fb 100644 --- a/src/Nazara/Core/Error.cpp +++ b/src/Nazara/Core/Error.cpp @@ -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) diff --git a/src/Nazara/Core/ErrorFlags.cpp b/src/Nazara/Core/ErrorFlags.cpp index 08c1d3e19..d29efbc5a 100644 --- a/src/Nazara/Core/ErrorFlags.cpp +++ b/src/Nazara/Core/ErrorFlags.cpp @@ -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) diff --git a/src/Nazara/Core/File.cpp b/src/Nazara/Core/File.cpp index db71f2d95..55587c9e0 100644 --- a/src/Nazara/Core/File.cpp +++ b/src/Nazara/Core/File.cpp @@ -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 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)) { diff --git a/src/Nazara/Core/FileLogger.cpp b/src/Nazara/Core/FileLogger.cpp index d8f23a1b1..6a94787bd 100644 --- a/src/Nazara/Core/FileLogger.cpp +++ b/src/Nazara/Core/FileLogger.cpp @@ -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) diff --git a/src/Nazara/Core/GuillotineBinPack.cpp b/src/Nazara/Core/GuillotineBinPack.cpp index 05f8736b5..69e3a1333 100644 --- a/src/Nazara/Core/GuillotineBinPack.cpp +++ b/src/Nazara/Core/GuillotineBinPack.cpp @@ -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(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(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(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 remainingRects(count); // La position du rectangle + std::vector 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::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) diff --git a/src/Nazara/Core/HardwareInfo.cpp b/src/Nazara/Core/HardwareInfo.cpp index 1ada7a794..af7f47e5d 100644 --- a/src/Nazara/Core/HardwareInfo.cpp +++ b/src/Nazara/Core/HardwareInfo.cpp @@ -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 clarté + // 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, ®isters[0], 4*sizeof(UInt32)); // On rajoute les 16 octets à la chaîne + std::memcpy(ptr, ®isters[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; } } diff --git a/src/Nazara/Core/LockGuard.cpp b/src/Nazara/Core/LockGuard.cpp index b59596a7c..31c1fe559 100644 --- a/src/Nazara/Core/LockGuard.cpp +++ b/src/Nazara/Core/LockGuard.cpp @@ -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(); diff --git a/src/Nazara/Core/Log.cpp b/src/Nazara/Core/Log.cpp index e554b7631..1a658c97e 100644 --- a/src/Nazara/Core/Log.cpp +++ b/src/Nazara/Core/Log.cpp @@ -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); diff --git a/src/Nazara/Core/MemoryManager.cpp b/src/Nazara/Core/MemoryManager.cpp index db58f2299..20dc17fa8 100644 --- a/src/Nazara/Core/MemoryManager.cpp +++ b/src/Nazara/Core/MemoryManager.cpp @@ -15,7 +15,7 @@ #include #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(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(¤tTime)); } + /*! + * \brief Uninitializes the MemoryManager + */ + void MemoryManager::Uninitialize() { #ifdef NAZARA_PLATFORM_WINDOWS @@ -334,5 +426,5 @@ namespace Nz } std::fclose(log); -} + } } diff --git a/src/Nazara/Core/MemoryStream.cpp b/src/Nazara/Core/MemoryStream.cpp index b311cd058..7940fee8a 100644 --- a/src/Nazara/Core/MemoryStream.cpp +++ b/src/Nazara/Core/MemoryStream.cpp @@ -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(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; } diff --git a/src/Nazara/Core/MemoryView.cpp b/src/Nazara/Core/MemoryView.cpp index 77c69bcb4..a636eb9a8 100644 --- a/src/Nazara/Core/MemoryView.cpp +++ b/src/Nazara/Core/MemoryView.cpp @@ -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(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(const_cast(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(size, static_cast(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(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; diff --git a/src/Nazara/Core/Mutex.cpp b/src/Nazara/Core/Mutex.cpp index 1245cd801..647fffc12 100644 --- a/src/Nazara/Core/Mutex.cpp +++ b/src/Nazara/Core/Mutex.cpp @@ -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(); diff --git a/src/Nazara/Core/ParameterList.cpp b/src/Nazara/Core/ParameterList.cpp index 5b63218af..1244b8b2c 100644 --- a/src/Nazara/Core/ParameterList.cpp +++ b/src/Nazara/Core/ParameterList.cpp @@ -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(converted); - return true; - } + double converted; + if (it->second.value.stringVal.ToDouble(&converted)) + { + *value = static_cast(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::max() && converted >= std::numeric_limits::min()) + long long converted; + if (it->second.value.stringVal.ToInteger(&converted)) { - *value = static_cast(converted); - return true; + if (converted <= std::numeric_limits::max() && converted >= std::numeric_limits::min()) + { + *value = static_cast(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 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 pair = m_parameters.insert(std::make_pair(name, Parameter())); @@ -307,6 +450,13 @@ namespace Nz PlacementNew(¶meter.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 pair = m_parameters.insert(std::make_pair(name, Parameter())); @@ -320,6 +470,13 @@ namespace Nz PlacementNew(¶meter.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 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 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 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 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 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: diff --git a/src/Nazara/Core/PluginManager.cpp b/src/Nazara/Core/PluginManager.cpp index ddfede54c..04fcafac7 100644 --- a/src/Nazara/Core/PluginManager.cpp +++ b/src/Nazara/Core/PluginManager.cpp @@ -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) diff --git a/src/Nazara/Core/Posix/FileImpl.cpp b/src/Nazara/Core/Posix/FileImpl.cpp index ddd8d4253..3fa93f6f2 100644 --- a/src/Nazara/Core/Posix/FileImpl.cpp +++ b/src/Nazara/Core/Posix/FileImpl.cpp @@ -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; diff --git a/src/Nazara/Core/Posix/SemaphoreImpl.cpp b/src/Nazara/Core/Posix/SemaphoreImpl.cpp index 4342cf1c6..eb1b7d1dd 100644 --- a/src/Nazara/Core/Posix/SemaphoreImpl.cpp +++ b/src/Nazara/Core/Posix/SemaphoreImpl.cpp @@ -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 } } diff --git a/src/Nazara/Core/PrimitiveList.cpp b/src/Nazara/Core/PrimitiveList.cpp index a9d2fc6ee..644f46e66 100644 --- a/src/Nazara/Core/PrimitiveList.cpp +++ b/src/Nazara/Core/PrimitiveList.cpp @@ -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); diff --git a/src/Nazara/Core/RefCounted.cpp b/src/Nazara/Core/RefCounted.cpp index db6ea7edf..f2ef2b926 100644 --- a/src/Nazara/Core/RefCounted.cpp +++ b/src/Nazara/Core/RefCounted.cpp @@ -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; diff --git a/src/Nazara/Core/Resource.cpp b/src/Nazara/Core/Resource.cpp index 080e4fd22..23fa6ea22 100644 --- a/src/Nazara/Core/Resource.cpp +++ b/src/Nazara/Core/Resource.cpp @@ -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; diff --git a/src/Nazara/Core/Semaphore.cpp b/src/Nazara/Core/Semaphore.cpp index 1a9afdc95..c5d9cc5b7 100644 --- a/src/Nazara/Core/Semaphore.cpp +++ b/src/Nazara/Core/Semaphore.cpp @@ -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); diff --git a/src/Nazara/Core/StdLogger.cpp b/src/Nazara/Core/StdLogger.cpp index 49752db26..783957ef1 100644 --- a/src/Nazara/Core/StdLogger.cpp +++ b/src/Nazara/Core/StdLogger.cpp @@ -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 diff --git a/src/Nazara/Core/Stream.cpp b/src/Nazara/Core/Stream.cpp index f8aab413e..3ddcb9fc7 100644 --- a/src/Nazara/Core/Stream.cpp +++ b/src/Nazara/Core/Stream.cpp @@ -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); diff --git a/src/Nazara/Core/String.cpp b/src/Nazara/Core/String.cpp index daa5cb85a..74c2afe80 100644 --- a/src/Nazara/Core/String.cpp +++ b/src/Nazara/Core/String.cpp @@ -2,7 +2,7 @@ // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp -///TODO: Réécrire une bonne partie des algorithmes employés (Relu jusqu'à 3538) +///TODO: Rewrite most of used algorithms (Reread to to line 4638) #include #include @@ -23,7 +23,7 @@ namespace Nz { namespace Detail { - // Cet algorithme est inspiré de la documentation de Qt + // This algorithm is inspired by the documentation of Qt inline std::size_t GetNewSize(std::size_t newSize) { if (newSize < 20) @@ -76,11 +76,26 @@ namespace Nz } } + /*! + * \class Nz::String + * \brief Core class that represents a string + */ + + /*! + * \brief Constructs a String object by default + */ + String::String() : m_sharedString(GetEmptyString()) { } + /*! + * \brief Constructs a String object with a character + * + * \param character Single character + */ + String::String(char character) { if (character != '\0') @@ -92,6 +107,13 @@ namespace Nz m_sharedString = GetEmptyString(); } + /*! + * \brief Constructs a String object with multiple times the same character + * + * \param rep Number of repetitions of the character + * \param character Single character + */ + String::String(std::size_t rep, char character) { if (rep > 0) @@ -105,11 +127,26 @@ namespace Nz m_sharedString = GetEmptyString(); } + /*! + * \brief Constructs a String object with multiple times the same string + * + * \param rep Number of repetitions of the string + * \param string String to multiply + */ + String::String(std::size_t rep, const char* string) : String(rep, string, (string) ? std::strlen(string) : 0) { } + /*! + * \brief Constructs a String object with multiple times the same string + * + * \param rep Number of repetitions of the string + * \param string String to multiply + * \param length Length of the string + */ + String::String(std::size_t rep, const char* string, std::size_t length) { std::size_t totalSize = rep*length; @@ -125,16 +162,36 @@ namespace Nz m_sharedString = GetEmptyString(); } + /*! + * \brief Constructs a String object with multiple times the same string + * + * \param rep Number of repetitions of the string + * \param string String to multiply + */ + String::String(std::size_t rep, const String& string) : String(rep, string.GetConstBuffer(), string.GetSize()) { } + /*! + * \brief Constructs a String object with a "C string" + * + * \param string String to represent + */ + String::String(const char* string) : String(string, (string) ? std::strlen(string) : 0) { } + /*! + * \brief Constructs a String object with a "C string" + * + * \param string String to represent + * \param length Length of the string + */ + String::String(const char* string, std::size_t length) { if (length > 0) @@ -146,31 +203,80 @@ namespace Nz m_sharedString = GetEmptyString(); } + /*! + * \brief Constructs a String object which is a copy of another + * + * \param string String to copy + */ + String::String(const std::string& string) : String(string.c_str(), string.size()) { } + /*! + * \brief Appends the character to the string + * \return A reference to this + * + * \param character Single character + * + * \see Insert + */ + String& String::Append(char character) { return Insert(m_sharedString->size, character); } + /*! + * \brief Appends the "C string" to the string + * \return A reference to this + * + * \param string String to add + * + * \see Insert + */ + String& String::Append(const char* string) { return Insert(m_sharedString->size, string); } + /*! + * \brief Appends the "C string" to the string + * \return A reference to this + * + * \param string String to add + * \param length Size of the string + * + * \see Insert + */ + String& String::Append(const char* string, std::size_t length) { return Insert(m_sharedString->size, string, length); } + /*! + * \brief Appends the string to the string + * \return A reference to this + * + * \param string String to add + * + * \see Insert + */ + String& String::Append(const String& string) { return Insert(m_sharedString->size, string); } + /*! + * \brief Clears the content of the string + * + * \param keepBuffer Should the buffer be kept + */ + void String::Clear(bool keepBuffer) { if (keepBuffer) @@ -182,21 +288,63 @@ namespace Nz ReleaseString(); } + /*! + * \Brief Checks whether the string contains the character + * \return true if found in the string + * + * \param character Single character + * \param start Index to begin the research + * \param flags Flag for the look up + * + * \see Find + */ + bool String::Contains(char character, std::intmax_t start, UInt32 flags) const { return Find(character, start, flags) != npos; } + /*! + * \Brief Checks whether the string contains the "C string" + * \return true if found in the string + * + * \param string String to search + * \param start Index to begin the research + * \param flags Flag for the look up + * + * \see Find + */ + bool String::Contains(const char* string, std::intmax_t start, UInt32 flags) const { return Find(string, start, flags) != npos; } + /*! + * \Brief Checks whether the string contains the string + * \return true if found in the string + * + * \param string String to search + * \param start Index to begin the research + * \param flags Flag for the look up + * + * \see Find + */ + bool String::Contains(const String& string, std::intmax_t start, UInt32 flags) const { return Find(string, start, flags) != npos; } + /*! + * \brief Counts the number of occurrences in the string + * \return Number of occurrences + * + * \param character Single character + * \param start Index to begin the research + * \param flags Flag for the look up + */ + unsigned int String::Count(char character, std::intmax_t start, UInt32 flags) const { if (character == '\0' || m_sharedString->size == 0) @@ -234,6 +382,15 @@ namespace Nz return count; } + /*! + * \brief Counts the number of occurrences in the string + * \return Number of occurrences + * + * \param string String to count + * \param start Index to begin the research + * \param flags Flag for the look up + */ + unsigned int String::Count(const char* string, std::intmax_t start, UInt32 flags) const { if (!string || !string[0] || m_sharedString->size == 0) @@ -331,11 +488,29 @@ namespace Nz return count; } + /*! + * \brief Counts the number of occurrences in the string + * \return Number of occurrences + * + * \param string String to count + * \param start Index to begin the research + * \param flags Flag for the look up + */ + unsigned int String::Count(const String& string, std::intmax_t start, UInt32 flags) const { return Count(string.GetConstBuffer(), start, flags); } + /*! + * \brief Counts the number of occurrences of any characters in the list in the string + * \return Number of occurrences + * + * \param string String to match + * \param start Index to begin the research + * \param flags Flag for the look up + */ + unsigned int String::CountAny(const char* string, std::intmax_t start, UInt32 flags) const { if (!string || !string[0] || m_sharedString->size == 0) @@ -424,11 +599,30 @@ namespace Nz return count; } + /*! + * \brief Counts the number of occurrences of any characters in the list in the string + * \return Number of occurrences + * + * \param string String to match + * \param start Index to begin the research + * \param flags Flag for the look up + */ + unsigned int String::CountAny(const String& string, std::intmax_t start, UInt32 flags) const { return CountAny(string.GetConstBuffer(), start, flags); } + /*! + * \brief Checks whether the string ends with the character + * \return true if it the case + * + * \param character Single character + * \param flags Flag for the look up + * + * \see StartsWith + */ + bool String::EndsWith(char character, UInt32 flags) const { if (m_sharedString->size == 0) @@ -437,14 +631,35 @@ namespace Nz if (flags & CaseInsensitive) return Detail::ToLower(m_sharedString->string[m_sharedString->size-1]) == Detail::ToLower(character); else - return m_sharedString->string[m_sharedString->size-1] == character; // character == '\0' sera toujours faux + return m_sharedString->string[m_sharedString->size-1] == character; // character == '\0' will always be false } + /*! + * \brief Checks whether the string ends with the "C string" + * \return true if it the case + * + * \param string String to match + * \param flags Flag for the look up + * + * \see StartsWith + */ + bool String::EndsWith(const char* string, UInt32 flags) const { return EndsWith(string, std::strlen(string), flags); } + /*! + * \brief Checks whether the string ends with the "C string" + * \return true if it the case + * + * \param string String to match + * \param length Size of the string + * \param flags Flag for the look up + * + * \see StartsWith + */ + bool String::EndsWith(const char* string, std::size_t length, UInt32 flags) const { if (!string || !string[0] || m_sharedString->size == 0 || length > m_sharedString->size) @@ -461,11 +676,30 @@ namespace Nz return std::strcmp(&m_sharedString->string[m_sharedString->size - length], string) == 0; } + /*! + * \brief Checks whether the string ends with the string + * \return true if it the case + * + * \param string String to match + * \param flags Flag for the look up + * + * \see StartsWith + */ + bool String::EndsWith(const String& string, UInt32 flags) const { return EndsWith(string.GetConstBuffer(), string.m_sharedString->size, flags); } + /*! + * \brief Finds the first index of the character in the string + * \return Index in the string + * + * \param character Single character + * \param start Index to begin the search + * \param flags Flag for the look up + */ + std::size_t String::Find(char character, std::intmax_t start, UInt32 flags) const { if (character == '\0' || m_sharedString->size == 0) @@ -501,6 +735,15 @@ namespace Nz } } + /*! + * \brief Finds the first index of the "C string" in the string + * \return Index in the string + * + * \param string String to match + * \param start Index to begin the search + * \param flags Flag for the look up + */ + std::size_t String::Find(const char* string, std::intmax_t start, UInt32 flags) const { if (!string || !string[0] || m_sharedString->size == 0) @@ -591,11 +834,29 @@ namespace Nz return npos; } + /*! + * \brief Finds the first index of the string in the string + * \return Index in the string + * + * \param string String to match + * \param start Index to begin the search + * \param flags Flag for the look up + */ + std::size_t String::Find(const String& string, std::intmax_t start, UInt32 flags) const { return Find(string.GetConstBuffer(), start, flags); } + /*! + * \brief Finds the first index of any characters in the list in the string + * \return Index in the string + * + * \param string String to match + * \param start Index to begin the search + * \param flags Flag for the look up + */ + std::size_t String::FindAny(const char* string, std::intmax_t start, UInt32 flags) const { if (m_sharedString->size == 0 || !string || !string[0]) @@ -674,11 +935,29 @@ namespace Nz return npos; } + /*! + * \brief Finds the first index of any characters in the list in the string + * \return Index in the string + * + * \param string String to match + * \param start Index to begin the search + * \param flags Flag for the look up + */ + std::size_t String::FindAny(const String& string, std::intmax_t start, UInt32 flags) const { return FindAny(string.GetConstBuffer(), start, flags); } + /*! + * \brief Finds the last index of the character in the string + * \return Index in the string + * + * \param character Single character + * \param start Index to begin the search + * \param flags Flag for the look up + */ + std::size_t String::FindLast(char character, std::intmax_t start, UInt32 flags) const { if (character == '\0' || m_sharedString->size == 0) @@ -716,6 +995,15 @@ namespace Nz return npos; } + /*! + * \brief Finds the last index of the "C string" in the string + * \return Index in the string + * + * \param string String to match + * \param start Index to begin the search + * \param flags Flag for the look up + */ + std::size_t String::FindLast(const char* string, std::intmax_t start, UInt32 flags) const { if (!string || !string[0] || m_sharedString->size == 0) @@ -728,14 +1016,14 @@ namespace Nz if (pos >= m_sharedString->size) return npos; - ///Algo 1.FindLast#3 (Taille du pattern inconnue) + ///Algo 1.FindLast#3 (Size of the pattern unknown) const char* ptr = &m_sharedString->string[pos]; if (flags & CaseInsensitive) { if (flags & HandleUtf8) { if (utf8::internal::is_trail(*ptr)) - utf8::unchecked::prior(ptr); // On s'assure d'avoir un pointeur vers le début d'un caractère + utf8::unchecked::prior(ptr); // We ensure to have one pointer pointing to the begin of the character utf8::unchecked::iterator it(ptr); const char* t = string; @@ -824,6 +1112,15 @@ namespace Nz return npos; } + /*! + * \brief Finds the last index of the string in the string + * \return Index in the string + * + * \param string String to match + * \param start Index to begin the search + * \param flags Flag for the look up + */ + std::size_t String::FindLast(const String& string, std::intmax_t start, UInt32 flags) const { if (string.m_sharedString->size == 0 || string.m_sharedString->size > m_sharedString->size) @@ -843,9 +1140,9 @@ namespace Nz { if (flags & HandleUtf8) { - ///Algo 1.FindLast#3 (Itérateur non-adapté) + ///Algo 1.FindLast#3 (Iterator non-adapted) if (utf8::internal::is_trail(*ptr)) - utf8::unchecked::prior(ptr); // On s'assure d'avoir un pointeur vers le début d'un caractère + utf8::unchecked::prior(ptr); // We ensure to have one pointer pointing to the begin of the character utf8::unchecked::iterator it(ptr); const char* t = string.GetConstBuffer(); @@ -878,7 +1175,7 @@ namespace Nz } else { - ///Algo 1.FindLast#4 (Taille du pattern connue) + ///Algo 1.FindLast#4 (Size of the pattern unknown) char c = Detail::ToLower(string.m_sharedString->string[string.m_sharedString->size-1]); for (;;) { @@ -904,7 +1201,7 @@ namespace Nz } else { - ///Algo 1.FindLast#4 (Taille du pattern connue) + ///Algo 1.FindLast#4 (Size of the pattern known) for (;;) { if (*ptr == string.m_sharedString->string[string.m_sharedString->size-1]) @@ -930,6 +1227,15 @@ namespace Nz return npos; } + /*! + * \brief Finds the last index of any characters in the list in the string + * \return Index in the string + * + * \param string String to match + * \param start Index to begin the search + * \param flags Flag for the look up + */ + std::size_t String::FindLastAny(const char* string, std::intmax_t start, UInt32 flags) const { if (!string || !string[0] || m_sharedString->size == 0) @@ -1016,11 +1322,29 @@ namespace Nz return npos; } + /*! + * \brief Finds the last index of any characters in the list in the string + * \return Index in the string + * + * \param string String to match + * \param start Index to begin the search + * \param flags Flag for the look up + */ + std::size_t String::FindLastAny(const String& string, std::intmax_t start, UInt32 flags) const { return FindLastAny(string.GetConstBuffer(), start, flags); } + /*! + * \brief Finds the last word in the string + * \return Index in the string + * + * \param string String to match + * \param start Index to begin the search + * \param flags Flag for the look up + */ + std::size_t String::FindLastWord(const char* string, std::intmax_t start, UInt32 flags) const { if (!string || !string[0] || m_sharedString->size == 0) @@ -1033,19 +1357,19 @@ namespace Nz if (pos >= m_sharedString->size) return npos; - ///Algo 2.FindLastWord#1 (Taille du pattern inconnue) + ///Algo 2.FindLastWord#1 (Size of the pattern unknown) const char* ptr = &m_sharedString->string[pos]; if (flags & HandleUtf8) { if (utf8::internal::is_trail(*ptr)) - utf8::unchecked::prior(ptr); // On s'assure d'avoir un pointeur vers le début d'un caractère + utf8::unchecked::prior(ptr); // We ensure to have a pointer pointing to the beginning of the string utf8::unchecked::iterator it(ptr); if (flags & CaseInsensitive) { - const char* t = string; // utf8(::unchecked)::next affecte l'itérateur en argument + const char* t = string; // utf8(::unchecked)::next affects the iterator on argument UInt32 c = Unicode::GetLowercase(utf8::unchecked::next(t)); do { @@ -1087,7 +1411,7 @@ namespace Nz } else { - const char* t = string; // utf8(::unchecked)::next affecte l'itérateur en argument + const char* t = string; // utf8(::unchecked)::next affects the iterator on argument UInt32 c = utf8::unchecked::next(t); do { @@ -1204,6 +1528,15 @@ namespace Nz return npos; } + /*! + * \brief Finds the last word in the string + * \return Index in the string + * + * \param string String to match + * \param start Index to begin the search + * \param flags Flag for the look up + */ + std::size_t String::FindLastWord(const String& string, std::intmax_t start, UInt32 flags) const { if (string.m_sharedString->size == 0 || string.m_sharedString->size > m_sharedString->size) @@ -1222,13 +1555,13 @@ namespace Nz if (flags & HandleUtf8) { if (utf8::internal::is_trail(*ptr)) - utf8::unchecked::prior(ptr); // On s'assure d'avoir un pointeur vers le début d'un caractère + utf8::unchecked::prior(ptr); // We ensure to have a pointer pointing to the beginning of the string utf8::unchecked::iterator it(ptr); if (flags & CaseInsensitive) { - const char* t = string.GetConstBuffer(); // utf8(::unchecked)::next affecte l'itérateur en argument + const char* t = string.GetConstBuffer(); // utf8(::unchecked)::next affects the iterator on argument UInt32 c = Unicode::GetLowercase(utf8::unchecked::next(t)); do { @@ -1270,7 +1603,7 @@ namespace Nz } else { - const char* t = string.GetConstBuffer(); // utf8(::unchecked)::next affecte l'itérateur en argument + const char* t = string.GetConstBuffer(); // utf8(::unchecked)::next affects the iterator on argument UInt32 c = utf8::unchecked::next(t); do { @@ -1313,7 +1646,7 @@ namespace Nz } else { - ///Algo 2.FindLastWord#2 (Taille du pattern connue) + ///Algo 2.FindLastWord#2 (Size of the pattern known) if (flags & CaseInsensitive) { char c = Detail::ToLower(string.m_sharedString->string[string.m_sharedString->size-1]); @@ -1380,6 +1713,15 @@ namespace Nz return npos; } + /*! + * \brief Finds the first word in the string + * \return Index in the string + * + * \param string String to match + * \param start Index to begin the search + * \param flags Flag for the look up + */ + std::size_t String::FindWord(const char* string, std::intmax_t start, UInt32 flags) const { if (!string || !string[0] || m_sharedString->size == 0) @@ -1392,18 +1734,18 @@ namespace Nz if (pos >= m_sharedString->size) return npos; - ///Algo 3.FindWord#3 (Taille du pattern inconnue) + ///Algo 3.FindWord#3 (Size of the pattern unknown) const char* ptr = m_sharedString->string.get(); if (flags & HandleUtf8) { if (utf8::internal::is_trail(*ptr)) - utf8::unchecked::prior(ptr); // On s'assure d'avoir un pointeur vers le début d'un caractère + utf8::unchecked::prior(ptr); // We ensure to have one pointer pointing to the begin of the character utf8::unchecked::iterator it(ptr); if (flags & CaseInsensitive) { - const char* t = string; // utf8(::unchecked)::next affecte l'itérateur en argument + const char* t = string; // utf8(::unchecked)::next affects the iterator on argument UInt32 c = Unicode::GetLowercase(utf8::unchecked::next(t)); do @@ -1443,7 +1785,7 @@ namespace Nz } else { - const char* t = string; // utf8(::unchecked)::next affecte l'itérateur en argument + const char* t = string; // utf8(::unchecked)::next affects the iterator on argument UInt32 c = Unicode::GetLowercase(utf8::unchecked::next(t)); do @@ -1552,6 +1894,15 @@ namespace Nz return npos; } + /*! + * \brief Finds the first word in the string + * \return Index in the string + * + * \param string String to match + * \param start Index to begin the search + * \param flags Flag for the look up + */ + std::size_t String::FindWord(const String& string, std::intmax_t start, UInt32 flags) const { if (string.m_sharedString->size == 0 || string.m_sharedString->size > m_sharedString->size) @@ -1567,15 +1918,15 @@ namespace Nz char* ptr = m_sharedString->string.get(); if (flags & HandleUtf8) { - ///Algo 3.FindWord#3 (Itérateur trop lent pour #2) + ///Algo 3.FindWord#3 (Iterator too slow for #2) if (utf8::internal::is_trail(*ptr)) - utf8::unchecked::prior(ptr); // On s'assure d'avoir un pointeur vers le début d'un caractère + utf8::unchecked::prior(ptr); // We ensure to have one pointer pointing to the begin of the character utf8::unchecked::iterator it(ptr); if (flags & CaseInsensitive) { - const char* t = string.GetConstBuffer(); // utf8(::unchecked)::next affecte l'itérateur en argument + const char* t = string.GetConstBuffer(); // utf8(::unchecked)::next affects the iterator on argument UInt32 c = Unicode::GetLowercase(utf8::unchecked::next(t)); do @@ -1615,7 +1966,7 @@ namespace Nz } else { - const char* t = string.GetConstBuffer(); // utf8(::unchecked)::next affecte l'itérateur en argument + const char* t = string.GetConstBuffer(); // utf8(::unchecked)::next affects the iterator on argument UInt32 c = Unicode::GetLowercase(utf8::unchecked::next(t)); do @@ -1656,7 +2007,7 @@ namespace Nz } else { - ///Algo 3.FindWord#2 (Taille du pattern connue) + ///Algo 3.FindWord#2 (Size of the pattern known) if (flags & CaseInsensitive) { char c = Detail::ToLower(string.m_sharedString->string[0]); @@ -1693,7 +2044,7 @@ namespace Nz { while ((ptr = std::strstr(ptr, string.GetConstBuffer())) != nullptr) { - // Si le mot est bien isolé + // If the word is really alone if ((ptr == m_sharedString->string.get() || std::isspace(*(ptr-1))) && (*(ptr+m_sharedString->size) == '\0' || std::isspace(*(ptr+m_sharedString->size)))) return ptr - m_sharedString->string.get(); @@ -1705,6 +2056,11 @@ namespace Nz return npos; } + /*! + * \brief Gets the raw buffer + * \return Raw buffer + */ + char* String::GetBuffer() { EnsureOwnership(); @@ -1712,31 +2068,61 @@ namespace Nz return m_sharedString->string.get(); } + /*! + * \brief Gets the capacity of the string + * \return Capacity of the string + */ + std::size_t String::GetCapacity() const { return m_sharedString->capacity; } + /*! + * \brief Gets the raw buffer + * \return Raw buffer + */ + const char* String::GetConstBuffer() const { return m_sharedString->string.get(); } + /*! + * \brief Gets the length of the string + * \return Length of the string with UTF-8 awareness + */ + std::size_t String::GetLength() const { return utf8::distance(m_sharedString->string.get(), &m_sharedString->string[m_sharedString->size]); } + /*! + * \brief Gets the size of the string + * \return Size of the string without UTF-8 awareness + */ + std::size_t String::GetSize() const { return m_sharedString->size; } + /*! + * \brief Gets the std::string corresponding + * \return String in UTF-8 + */ + std::string String::GetUtf8String() const { return std::string(m_sharedString->string.get(), m_sharedString->size); } + /*! + * \brief Gets the std::string corresponding + * \return String in UTF-16 + */ + std::u16string String::GetUtf16String() const { if (m_sharedString->size == 0) @@ -1750,6 +2136,11 @@ namespace Nz return str; } + /*! + * \brief Gets the std::string corresponding + * \return String in UTF-32 + */ + std::u32string String::GetUtf32String() const { if (m_sharedString->size == 0) @@ -1763,6 +2154,11 @@ namespace Nz return str; } + /*! + * \brief Gets the std::wstring corresponding + * \return String in Wide + */ + std::wstring String::GetWideString() const { static_assert(sizeof(wchar_t) == 2 || sizeof(wchar_t) == 4, "wchar_t size is not supported"); @@ -1772,7 +2168,7 @@ namespace Nz std::wstring str; str.reserve(m_sharedString->size); - if (sizeof(wchar_t) == 4) // Je veux du static_if :( + if (sizeof(wchar_t) == 4) // I want a static_if :( utf8::utf8to32(begin(), end(), std::back_inserter(str)); else { @@ -1791,6 +2187,14 @@ namespace Nz return str; } + /*! + * \brief Gets the word until next separator + * \return Word string + * + * \param start Index to begin the search + * \param flags Flag for the look up + */ + String String::GetWord(unsigned int index, UInt32 flags) const { std::size_t startPos = GetWordPosition(index, flags); @@ -1828,6 +2232,14 @@ namespace Nz return SubString(startPos, endPos); } + /*! + * \brief Gets the word position + * \return Position of the beginning of the word + * + * \param start Index to begin the search + * \param flags Flag for the look up + */ + std::size_t String::GetWordPosition(unsigned int index, UInt32 flags) const { if (m_sharedString->size == 0) @@ -1878,16 +2290,41 @@ namespace Nz return npos; } + /*! + * \brief Inserts the character into the string + * \return A reference to this + * + * \param pos Position in the string + * \param character Single character + */ + String& String::Insert(std::intmax_t pos, char character) { return Insert(pos, &character, 1); } + /*! + * \brief Inserts the "C string" into the string + * \return A reference to this + * + * \param pos Position in the string + * \param string String to add + */ + String& String::Insert(std::intmax_t pos, const char* string) { return Insert(pos, string, std::strlen(string)); } + /*! + * \brief Inserts the "C string" into the string + * \return A reference to this + * + * \param pos Position in the string + * \param string String to add + * \param length Size of the string + */ + String& String::Insert(std::intmax_t pos, const char* string, std::size_t length) { if (length == 0) @@ -1898,7 +2335,7 @@ namespace Nz std::size_t start = std::min(pos, m_sharedString->size); - // Si le buffer est déjà suffisamment grand + // If buffer is already big enough if (m_sharedString->capacity >= m_sharedString->size + length) { EnsureOwnership(); @@ -1933,21 +2370,49 @@ namespace Nz return *this; } + /*! + * \brief Inserts the string into the string + * \return A reference to this + * + * \param pos Position in the string + * \param string String to add + */ + String& String::Insert(std::intmax_t pos, const String& string) { return Insert(pos, string.GetConstBuffer(), string.m_sharedString->size); } + /*! + * \brief Checks whether the string is empty + * \return true if string is empty + */ + bool String::IsEmpty() const { return m_sharedString->size == 0; } + /*! + * \brief Checks whether the string is null + * \return true if string is null + */ + bool String::IsNull() const { return m_sharedString.get() == GetEmptyString().get(); } + /*! + * \brief Checks whether the string is a number + * \return true if string is a number + * + * \param base Base of the number + * \param flags Flag for the look up + * + * \remark Produces a NazaraError if base is not in [2, 36( with NAZARA_CORE_SAFE defined + */ + bool String::IsNumber(UInt8 base, UInt32 flags) const { #if NAZARA_CORE_SAFE @@ -2010,6 +2475,13 @@ namespace Nz return true; } + /*! + * \brief Checks whether the string matches the pattern + * \return true if string matches + * + * \param pattern Pattern to search + */ + bool String::Match(const char* pattern) const { if (m_sharedString->size == 0 || !pattern) @@ -2057,37 +2529,91 @@ namespace Nz return !*pattern; } + /*! + * \brief Checks whether the string matches the pattern + * \return true if string matches + * + * \param pattern Pattern to search + */ + bool String::Match(const String& pattern) const { return Match(pattern.m_sharedString->string.get()); } + /*! + * \brief Prepends the character to the string + * \return A reference to this + * + * \param character Single character + * + * \see Insert + */ + String& String::Prepend(char character) { return Insert(0, character); } + /*! + * \brief Prepends the "C string" to the string + * \return A reference to this + * + * \param string String to add + * + * \see Insert + */ + String& String::Prepend(const char* string) { return Insert(0, string); } + /*! + * \brief Prepends the "C string" to the string + * \return A reference to this + * + * \param string String to add + * \param length Size of the string + * + * \see Insert + */ + String& String::Prepend(const char* string, std::size_t length) { return Insert(0, string, length); } + /*! + * \brief Prepends the string to the string + * \return A reference to this + * + * \param string String to add + * + * \see Insert + */ + String& String::Prepend(const String& string) { return Insert(0, string); } + /*! + * \brief Replaces the old character by the new one + * \return Number of changes + * + * \param oldCharacter Pattern to find + * \param newCharacter Pattern to change for + * \param start Index to begin the search + * \param flags Flag for the look up + */ + unsigned int String::Replace(char oldCharacter, char newCharacter, std::intmax_t start, UInt32 flags) { if (oldCharacter == '\0' || oldCharacter == newCharacter) return 0; - if (newCharacter == '\0') // Dans ce cas, il faut passer par un algorithme plus complexe + if (newCharacter == '\0') // In this case, we must use a more advanced algorithm return Replace(String(oldCharacter), String(), start); if (start < 0) @@ -2146,11 +2672,33 @@ namespace Nz return count; } + /*! + * \brief Replaces the old "C string" by the new one + * \return Number of changes + * + * \param oldCharacter Pattern to find + * \param newCharacter Pattern to change for + * \param start Index to begin the search + * \param flags Flag for the look up + */ + unsigned int String::Replace(const char* oldString, const char* replaceString, std::intmax_t start, UInt32 flags) { return Replace(oldString, std::strlen(oldString), replaceString, std::strlen(replaceString), start, flags); } + /*! + * \brief Replaces the old "C string" by the new one + * \return Number of changes + * + * \param oldCharacter Pattern to find + * \param oldLength Length of the old string + * \param newCharacter Pattern to change for + * \param Length of the new string + * \param start Index to begin the search + * \param flags Flag for the look up + */ + unsigned int String::Replace(const char* oldString, std::size_t oldLength, const char* replaceString, std::size_t replaceLength, std::intmax_t start, UInt32 flags) { if (oldLength == 0) @@ -2168,7 +2716,7 @@ namespace Nz { bool found = false; - // Si aucun changement de taille n'est nécessaire, nous pouvons alors utiliser un algorithme bien plus rapide + // If no size change is necessary, we can thus use a quicker algorithm while ((pos = Find(oldString, pos, flags)) != npos) { if (!found) @@ -2183,10 +2731,10 @@ namespace Nz ++count; } } - else ///TODO: Algorithme de remplacement sans changement de buffer (si replaceLength < oldLength) + else ///TODO: Replacement algorithm without changing the buffer (if replaceLength < oldLength) { std::size_t newSize = m_sharedString->size + Count(oldString)*(replaceLength - oldLength); - if (newSize == m_sharedString->size) // Alors c'est que Count(oldString) == 0 + if (newSize == m_sharedString->size) // Then it's the fact that Count(oldString) == 0 return 0; auto newString = std::make_shared(newSize); @@ -2217,18 +2765,40 @@ namespace Nz return count; } + /*! + * \brief Replaces the old string by the new one + * \return Number of changes + * + * \param oldCharacter Pattern to find + * \param newCharacter Pattern to change for + * \param start Index to begin the search + * \param flags Flag for the look up + */ + unsigned int String::Replace(const String& oldString, const String& replaceString, std::intmax_t start, UInt32 flags) { return Replace(oldString.GetConstBuffer(), oldString.m_sharedString->size, replaceString.GetConstBuffer(), replaceString.m_sharedString->size, start, flags); } + /*! + * \brief Replaces the old characters in the list by the new one + * \return Number of changes + * + * \param oldCharacters Pattern to find + * \param newCharacter Pattern to change for + * \param start Index to begin the search + * \param flags Flag for the look up + * + * \remark Does not handle UTF-8 currently + */ + unsigned int String::ReplaceAny(const char* oldCharacters, char replaceCharacter, std::intmax_t start, UInt32 flags) { - ///FIXME: Ne gère pas l'UTF-8 + ///FIXME: Does not handle UTF-8 if (!oldCharacters || !oldCharacters[0]) return 0; - /*if (replaceCharacter == '\0') // Dans ce cas, il faut passer par un algorithme plus complexe + /*if (replaceCharacter == '\0') // In this case, we must use a more advance algorithm return ReplaceAny(String(oldCharacters), String(), start);*/ if (start < 0) @@ -2454,6 +3024,14 @@ namespace Nz } */ + /*! + * \brief Reserves enough memory for the buffer size + * + * \param bufferSize Size of the buffer to allocate + * + * \remark If bufferSize is smaller than the old one, nothing is done + */ + void String::Reserve(std::size_t bufferSize) { if (m_sharedString->capacity > bufferSize) @@ -2468,6 +3046,14 @@ namespace Nz m_sharedString = std::move(newString); } + /*! + * \brief Resizes the string + * \return A reference to this + * + * \param size Target size + * \param flags Flag for the look up + */ + String& String::Resize(std::intmax_t size, UInt32 flags) { if (size == 0) @@ -2510,6 +3096,14 @@ namespace Nz return *this; } + /*! + * \brief Resize a copy of the string + * \return A copy of what would be the string resized + * + * \param size Target size + * \param flags Flag for the look up + */ + String String::Resized(std::intmax_t size, UInt32 flags) const { if (size < 0) @@ -2542,6 +3136,11 @@ namespace Nz return String(std::move(sharedStr)); } + /*! + * \brief Reverses the string + * \return A reference to this + */ + String& String::Reverse() { if (m_sharedString->size != 0) @@ -2556,6 +3155,11 @@ namespace Nz return *this; } + /*! + * \brief Reverses a copy of the string + * \return A copy of what would be the string reversed + */ + String String::Reversed() const { if (m_sharedString->size == 0) @@ -2573,6 +3177,13 @@ namespace Nz return String(std::move(sharedStr)); } + /*! + * \brief Sets the string to the character + * \return A reference to this + * + * \param character Single character + */ + String& String::Set(char character) { if (character != '\0') @@ -2597,6 +3208,15 @@ namespace Nz return *this; } + + /*! + * \brief Sets the string with multiple times the same character + * \return A reference to this + * + * \param rep Number of repetitions of the character + * \param character Single character + */ + String& String::Set(std::size_t rep, char character) { if (rep > 0) @@ -2620,11 +3240,28 @@ namespace Nz return *this; } + /*! + * \brief Sets the string with multiple times the same string + * \return A reference to this + * + * \param rep Number of repetitions of the string + * \param string String to multiply + */ + String& String::Set(std::size_t rep, const char* string) { return Set(rep, string, (string) ? std::strlen(string) : 0); } + /*! + * \brief Sets the string with multiple times the same string + * \return A reference to this + * + * \param rep Number of repetitions of the string + * \param string String to multiply + * \param length Length of the string + */ + String& String::Set(std::size_t rep, const char* string, std::size_t length) { std::size_t totalSize = rep*length; @@ -2650,16 +3287,39 @@ namespace Nz return *this; } + /*! + * \brief Sets the string with multiple times the same string + * \return A reference to this + * + * \param rep Number of repetitions of the string + * \param string String to multiply + */ + String& String::Set(std::size_t rep, const String& string) { return Set(rep, string.GetConstBuffer(), string.m_sharedString->size); } + /*! + * \brief Sets the string with other "C string" + * \return A reference to this + * + * \param string String to copy + */ + String& String::Set(const char* string) { return Set(string, (string) ? std::strlen(string) : 0); } + /*! + * \brief Sets the string with other "C string" + * \return A reference to this + * + * \param string String to represent + * \param length Length of the string + */ + String& String::Set(const char* string, std::size_t length) { if (length > 0) @@ -2682,11 +3342,25 @@ namespace Nz return *this; } + /*! + * \brief Sets the string with a std::string + * \return A reference to this + * + * \param string String to copy + */ + String& String::Set(const std::string& string) { return Set(string.data(), string.size()); } + /*! + * \brief Sets the string with other string + * \return A reference to this + * + * \param string String to copy + */ + String& String::Set(const String& string) { m_sharedString = string.m_sharedString; @@ -2694,6 +3368,13 @@ namespace Nz return *this; } + /*! + * \brief Sets the string by move semantic + * \return A reference to this + * + * \param string String to move + */ + String& String::Set(String&& string) noexcept { std::swap(m_sharedString, string.m_sharedString); @@ -2701,6 +3382,13 @@ namespace Nz return *this; } + /*! + * \brief Simplifies a copy of the string + * \return A copy of what would be the string simplified + * + * \param flags Flag for the look up + */ + String String::Simplified(UInt32 flags) const { if (m_sharedString->size == 0) @@ -2763,11 +3451,28 @@ namespace Nz return String(std::move(newString)); } + /*! + * \brief Simplifies the string + * \return A reference to this + * + * \param flags Flag for the look up + */ + String& String::Simplify(UInt32 flags) { return Set(Simplified(flags)); } + /*! + * \brief Splits the string into others + * \return The number of splits + * + * \param result Resulting tokens + * \param separation Separation character + * \param start Index for the beginning of the search + * \param flags Flag for the look up + */ + unsigned int String::Split(std::vector& result, char separation, std::intmax_t start, UInt32 flags) const { if (separation == '\0' || m_sharedString->size == 0) @@ -2800,11 +3505,32 @@ namespace Nz return result.size(); } + /*! + * \brief Splits the string into others + * \return The number of splits + * + * \param result Resulting tokens + * \param separation Separation string + * \param start Index for the beginning of the search + * \param flags Flag for the look up + */ + unsigned int String::Split(std::vector& result, const char* separation, std::intmax_t start, UInt32 flags) const { return Split(result, separation, std::strlen(separation), start, flags); } + /*! + * \brief Splits the string into others + * \return The number of splits + * + * \param result Resulting tokens + * \param separation Separation String + * \param length Length of the string + * \param start Index for the beginning of the search + * \param flags Flag for the look up + */ + unsigned int String::Split(std::vector& result, const char* separation, std::size_t length, std::intmax_t start, UInt32 flags) const { if (m_sharedString->size == 0) @@ -2848,11 +3574,31 @@ namespace Nz return result.size()-oldSize; } + /*! + * \brief Splits the string into others + * \return The number of splits + * + * \param result Resulting tokens + * \param separation Separation string + * \param start Index for the beginning of the search + * \param flags Flag for the look up + */ + unsigned int String::Split(std::vector& result, const String& separation, std::intmax_t start, UInt32 flags) const { return Split(result, separation.m_sharedString->string.get(), separation.m_sharedString->size, start, flags); } + /*! + * \brief Splits the string into others + * \return The number of splits + * + * \param result Resulting tokens + * \param separation List of characters of separation + * \param start Index for the beginning of the search + * \param flags Flag for the look up + */ + unsigned int String::SplitAny(std::vector& result, const char* separations, std::intmax_t start, UInt32 flags) const { if (m_sharedString->size == 0) @@ -2884,11 +3630,31 @@ namespace Nz return result.size()-oldSize; } + /*! + * \brief Splits the string into others + * \return The number of splits + * + * \param result Resulting tokens + * \param separation List of characters of separation + * \param start Index for the beginning of the search + * \param flags Flag for the look up + */ + unsigned int String::SplitAny(std::vector& result, const String& separations, std::intmax_t start, UInt32 flags) const { return SplitAny(result, separations.m_sharedString->string.get(), start, flags); } + /*! + * \brief Checks whether the string begins with the character + * \return true if it the case + * + * \param character Single character + * \param flags Flag for the look up + * + * \see EndsWith + */ + bool String::StartsWith(char character, UInt32 flags) const { if (character == '\0' || m_sharedString->size == 0) @@ -2900,6 +3666,16 @@ namespace Nz return m_sharedString->string[0] == character; } + /*! + * \brief Checks whether the string begins with the "C string" + * \return true if it the case + * + * \param string String to match + * \param flags Flag for the look up + * + * \see EndsWith + */ + bool String::StartsWith(const char* string, UInt32 flags) const { if (!string || !string[0] || m_sharedString->size == 0) @@ -2960,6 +3736,16 @@ namespace Nz return false; } + /*! + * \brief Checks whether the string begins with the string + * \return true if it the case + * + * \param string String to match + * \param flags Flag for the look up + * + * \see EndsWith + */ + bool String::StartsWith(const String& string, UInt32 flags) const { if (string.m_sharedString->size == 0) @@ -3009,6 +3795,14 @@ namespace Nz return false; } + /*! + * \brief Returns a sub string of the string + * \return SubString + * + * \param startPos Index for the beginning of the search + * \param endPos Index for the end of the search + */ + String String::SubString(std::intmax_t startPos, std::intmax_t endPos) const { if (startPos < 0) @@ -3035,6 +3829,17 @@ namespace Nz return String(std::move(str)); } + /*! + * \brief Returns a sub string of the string from a character + * \return SubString + * + * \param charater Pattern to find + * \param startPos Index for the beginning of the search + * \param fromLast beginning by the end + * \param include Include the character + * \param flags Flag for the look up + */ + String String::SubStringFrom(char character, std::intmax_t startPos, bool fromLast, bool include, UInt32 flags) const { if (character == '\0') @@ -3054,11 +3859,34 @@ namespace Nz return SubString(pos + ((include) ? 0 : 1)); } + /*! + * \brief Returns a sub string of the string from a string + * \return SubString + * + * \param string Pattern to find + * \param startPos Index for the beginning of the search + * \param fromLast beginning by the end + * \param include Include the character + * \param flags Flag for the look up + */ + String String::SubStringFrom(const char* string, std::intmax_t startPos, bool fromLast, bool include, UInt32 flags) const { return SubStringFrom(string, std::strlen(string), startPos, fromLast, include, flags); } + /*! + * \brief Returns a sub string of the string from a string + * \return SubString + * + * \param string Pattern to find + * \param length Size of the string + * \param startPos Index for the beginning of the search + * \param fromLast beginning by the end + * \param include Include the character + * \param flags Flag for the look up + */ + String String::SubStringFrom(const char* string, std::size_t length, std::intmax_t startPos, bool fromLast, bool include, UInt32 flags) const { std::size_t pos; @@ -3075,11 +3903,33 @@ namespace Nz return SubString(pos + ((include) ? 0 : length)); } + /*! + * \brief Returns a sub string of the string from a string + * \return SubString + * + * \param string Pattern to find + * \param startPos Index for the beginning of the search + * \param fromLast beginning by the end + * \param include Include the character + * \param flags Flag for the look up + */ + String String::SubStringFrom(const String& string, std::intmax_t startPos, bool fromLast, bool include, UInt32 flags) const { return SubStringFrom(string.GetConstBuffer(), string.m_sharedString->size, startPos, fromLast, include, flags); } + /*! + * \brief Returns a sub string of the string up to a character + * \return SubString + * + * \param charater Pattern to find + * \param startPos Index for the beginning of the search + * \param toLast beginning by the end + * \param include Include the character + * \param flags Flag for the look up + */ + String String::SubStringTo(char character, std::intmax_t startPos, bool toLast, bool include, UInt32 flags) const { if (character == '\0') @@ -3099,11 +3949,34 @@ namespace Nz return SubString(0, pos+((include) ? 1 : 0)-1); } + /*! + * \brief Returns a sub string of the string up to a string + * \return SubString + * + * \param string Pattern to find + * \param startPos Index for the beginning of the search + * \param toLast beginning by the end + * \param include Include the character + * \param flags Flag for the look up + */ + String String::SubStringTo(const char* string, std::intmax_t startPos, bool toLast, bool include, UInt32 flags) const { return SubStringTo(string, std::strlen(string), startPos, toLast, include, flags); } + /*! + * \brief Returns a sub string of the string up to a string + * \return SubString + * + * \param string Pattern to find + * \param length Size of the string + * \param startPos Index for the beginning of the search + * \param toLast beginning by the end + * \param include Include the character + * \param flags Flag for the look up + */ + String String::SubStringTo(const char* string, std::size_t length, std::intmax_t startPos, bool toLast, bool include, UInt32 flags) const { std::size_t pos; @@ -3120,16 +3993,41 @@ namespace Nz return SubString(0, pos+((include) ? length : 0)-1); } + /*! + * \brief Returns a sub string of the string up to a string + * \return SubString + * + * \param string Pattern to find + * \param startPos Index for the beginning of the search + * \param toLast beginning by the end + * \param include Include the character + * \param flags Flag for the look up + */ + String String::SubStringTo(const String& string, std::intmax_t startPos, bool toLast, bool include, UInt32 flags) const { return SubStringTo(string.GetConstBuffer(), string.m_sharedString->size, startPos, toLast, include, flags); } + /*! + * \brief Swaps the content with the other string + * + * \param str Other string to swap with + */ + void String::Swap(String& str) { std::swap(m_sharedString, str.m_sharedString); } + /*! + * \brief Converts the string to boolean + * \return true if successful + * + * \param value Boolean to convert to + * \param flags Flag for the look up + */ + bool String::ToBool(bool* value, UInt32 flags) const { if (m_sharedString->size == 0) @@ -3150,7 +4048,7 @@ namespace Nz else { if (flags & CaseInsensitive) - word = word.ToLower(); // Les mots identifiés sont en ASCII, inutile de passer le flag unicode + word = word.ToLower(); // The identified words are in ASCII, no use of Unicode flag if (word == "true") { @@ -3169,6 +4067,14 @@ namespace Nz return true; } + /*! + * \brief Converts the string to double + * \return true if successful + * + * \param value Double to convert to + * \param flags Flag for the look up + */ + bool String::ToDouble(double* value) const { if (m_sharedString->size == 0) @@ -3180,6 +4086,14 @@ namespace Nz return true; } + /*! + * \brief Converts the string to integer + * \return true if successful + * + * \param value Integer to convert to + * \param flags Flag for the look up + */ + bool String::ToInteger(long long* value, UInt8 base) const { if (value) @@ -3193,6 +4107,13 @@ namespace Nz return IsNumber(base); } + /*! + * \brief Converts the string to lower + * \return Lower string + * + * \param flags Flag for the look up + */ + String String::ToLower(UInt32 flags) const { if (m_sharedString->size == 0) @@ -3225,6 +4146,13 @@ namespace Nz } } + /*! + * \brief Converts the string to upper + * \return Upper string + * + * \param flags Flag for the look up + */ + String String::ToUpper(UInt32 flags) const { if (m_sharedString->size == 0) @@ -3257,16 +4185,38 @@ namespace Nz } } + /*! + * \brief Trims the string + * \return A reference to this + * + * \param flags Flag for the look up + */ + String& String::Trim(UInt32 flags) { return Set(Trimmed(flags)); } + /*! + * \brief Trims the string from a character + * \return A reference to this + * + * \param character Character to suppress + * \param flags Flag for the look up + */ + String& String::Trim(char character, UInt32 flags) { return Set(Trimmed(character, flags)); } + /*! + * \brief Trims a copy of the string + * \return A copy of what would be the string trimmed + * + * \param flags Flag for the look up + */ + String String::Trimmed(UInt32 flags) const { if (m_sharedString->size == 0) @@ -3331,6 +4281,14 @@ namespace Nz return SubString(startPos, endPos); } + /*! + * \brief Trims a copy of the string from a character + * \return A copy of what would be the string trimmed + * + * \param character Character to suppress + * \param flags Flag for the look up + */ + String String::Trimmed(char character, UInt32 flags) const { if (m_sharedString->size == 0) @@ -3383,31 +4341,67 @@ namespace Nz return SubString(startPos, endPos); } + /*! + * \brief Returns an iterator pointing to the beginning of the string + * \return beginning of the string + */ + char* String::begin() { return m_sharedString->string.get(); } + /*! + * \brief Returns an iterator pointing to the beginning of the string + * \return beginning of the string + */ + const char* String::begin() const { return m_sharedString->string.get(); } + /*! + * \brief Returns an iterator pointing to the end of the string + * \return End of the string + */ + char* String::end() { return &m_sharedString->string[m_sharedString->size]; } + /*! + * \brief Returns an iterator pointing to the end of the string + * \return End of the string + */ + const char* String::end() const { return &m_sharedString->string[m_sharedString->size]; } + /*! + * \brief Pushed the character to the front of the string + * + * \param c Single character + * + * \see Prepend + */ + void String::push_front(char c) { Prepend(c); } + /*! + * \brief Pushed the character to the back of the string + * + * \param c Single character + * + * \see Append + */ + void String::push_back(char c) { Append(c); @@ -3434,11 +4428,25 @@ namespace Nz } */ + /*! + * \brief Converts the string to std::string + * \return std::string representation + */ + String::operator std::string() const { return std::string(m_sharedString->string.get(), m_sharedString->size); } + /*! + * \brief Gets the ith character in the string + * \return A reference to the character + * + * \param pos Index of the character + * + * \remark If pos is greather than the size, Resize is called + */ + char& String::operator[](std::size_t pos) { EnsureOwnership(); @@ -3449,6 +4457,15 @@ namespace Nz return m_sharedString->string[pos]; } + /*! + * \brief Gets the ith character in the string + * \return The character + * + * \param pos Index of the character + * + * \remark Produces a NazaraError if pos is greather than the size + */ + char String::operator[](std::size_t pos) const { #if NAZARA_CORE_SAFE @@ -3462,31 +4479,73 @@ namespace Nz return m_sharedString->string[pos]; } + /*! + * \brief Assigns the string to the character + * \return A reference to this + * + * \param character Single character + */ + String& String::operator=(char character) { return Set(character); } + /*! + * \brief Assigns the string with other "C string" + * \return A reference to this + * + * \param string String to copy + */ + String& String::operator=(const char* string) { return Set(string); } + /*! + * \brief Assigns the string with a std::string + * \return A reference to this + * + * \param string String to copy + */ + String& String::operator=(const std::string& string) { return Set(string); } + /*! + * \brief Assigns the string with other string + * \return A reference to this + * + * \param string String to copy + */ + String& String::operator=(const String& string) { return Set(string); } + /*! + * \brief Assigns the string by move semantic + * \return A reference to this + * + * \param string String to move + */ + String& String::operator=(String&& string) noexcept { return Set(string); } + /*! + * \brief Concatenates the character to the string + * \return String which is the result of the concatenation + * + * \param character Single character + */ + String String::operator+(char character) const { if (character == '\0') @@ -3499,6 +4558,13 @@ namespace Nz return String(std::move(str)); } + /*! + * \brief Concatenates the "C string" to the string + * \return String which is the result of the concatenation + * + * \param string String to add + */ + String String::operator+(const char* string) const { if (!string || !string[0]) @@ -3518,6 +4584,13 @@ namespace Nz return String(std::move(str)); } + /*! + * \brief Concatenates the std::string to the string + * \return String which is the result of the concatenation + * + * \param string String to add + */ + String String::operator+(const std::string& string) const { if (string.empty()) @@ -3533,6 +4606,13 @@ namespace Nz return String(std::move(str)); } + /*! + * \brief Concatenates the string to the string + * \return String which is the result of the concatenation + * + * \param string String to add + */ + String String::operator+(const String& string) const { if (string.m_sharedString->size == 0) @@ -3548,26 +4628,61 @@ namespace Nz return String(std::move(str)); } + /*! + * \brief Concatenates the character to this string + * \return A reference to this + * + * \param character Single character + */ + String& String::operator+=(char character) { return Insert(m_sharedString->size, character); } + /*! + * \brief Concatenates the "C string" to this string + * \return A reference to this + * + * \param string String to add + */ + String& String::operator+=(const char* string) { return Insert(m_sharedString->size, string); } + /*! + * \brief Concatenates the std::string to this string + * \return A reference to this + * + * \param string String to add + */ + String& String::operator+=(const std::string& string) { return Insert(m_sharedString->size, string.c_str(), string.size()); } + /*! + * \brief Concatenates the string to this string + * \return A reference to this + * + * \param string String to add + */ + String& String::operator+=(const String& string) { return Insert(m_sharedString->size, string); } + /*! + * \brief Checks whether the string is equal to the character + * \return true if it is the case + * + * \param character Single character + */ + bool String::operator==(char character) const { if (m_sharedString->size == 0) @@ -3579,6 +4694,13 @@ namespace Nz return m_sharedString->string[0] == character; } + /*! + * \brief Checks whether the string is equal to the "C string" + * \return true if it is the case + * + * \param string String to compare + */ + bool String::operator==(const char* string) const { if (m_sharedString->size == 0) @@ -3590,6 +4712,13 @@ namespace Nz return std::strcmp(GetConstBuffer(), string) == 0; } + /*! + * \brief Checks whether the string is equal to the std::string + * \return true if it is the case + * + * \param string String to compare + */ + bool String::operator==(const std::string& string) const { if (m_sharedString->size == 0 || string.empty()) @@ -3601,6 +4730,13 @@ namespace Nz return std::strcmp(GetConstBuffer(), string.c_str()) == 0; } + /*! + * \brief Checks whether the string is equal to the character + * \return false if it is the case + * + * \param character Single character + */ + bool String::operator!=(char character) const { if (m_sharedString->size == 0) @@ -3615,6 +4751,13 @@ namespace Nz return m_sharedString->string[0] != character; } + /*! + * \brief Checks whether the string is equal to the "C string" + * \return false if it is the case + * + * \param string String to compare + */ + bool String::operator!=(const char* string) const { if (m_sharedString->size == 0) @@ -3626,6 +4769,13 @@ namespace Nz return std::strcmp(GetConstBuffer(), string) != 0; } + /*! + * \brief Checks whether the string is equal to the std::string + * \return false if it is the case + * + * \param string String to compare + */ + bool String::operator!=(const std::string& string) const { if (m_sharedString->size == 0 || string.empty()) @@ -3637,6 +4787,13 @@ namespace Nz return std::strcmp(GetConstBuffer(), string.c_str()) != 0; } + /*! + * \brief Checks whether the string is less than the character + * \return true if it is the case + * + * \param character Single character + */ + bool String::operator<(char character) const { if (character == '\0') @@ -3648,6 +4805,13 @@ namespace Nz return m_sharedString->string[0] < character; } + /*! + * \brief Checks whether the string is less than the "C string" + * \return true if it is the case + * + * \param string String to compare + */ + bool String::operator<(const char* string) const { if (!string || !string[0]) @@ -3659,6 +4823,13 @@ namespace Nz return std::strcmp(GetConstBuffer(), string) < 0; } + /*! + * \brief Checks whether the string is less than the std::string + * \return true if it is the case + * + * \param string String to compare + */ + bool String::operator<(const std::string& string) const { if (string.empty()) @@ -3670,6 +4841,13 @@ namespace Nz return std::strcmp(GetConstBuffer(), string.c_str()) < 0; } + /*! + * \brief Checks whether the string is less or equal than the character + * \return true if it is the case + * + * \param character Single character + */ + bool String::operator<=(char character) const { if (m_sharedString->size == 0) @@ -3681,6 +4859,13 @@ namespace Nz return m_sharedString->string[0] < character || (m_sharedString->string[0] == character && m_sharedString->size == 1); } + /*! + * \brief Checks whether the string is less or equal than the "C string" + * \return true if it is the case + * + * \param string String to compare + */ + bool String::operator<=(const char* string) const { if (m_sharedString->size == 0) @@ -3692,6 +4877,13 @@ namespace Nz return std::strcmp(GetConstBuffer(), string) <= 0; } + /*! + * \brief Checks whether the string is less or equal than the std::string + * \return true if it is the case + * + * \param string String to compare + */ + bool String::operator<=(const std::string& string) const { if (m_sharedString->size == 0) @@ -3703,6 +4895,13 @@ namespace Nz return std::strcmp(GetConstBuffer(), string.c_str()) <= 0; } + /*! + * \brief Checks whether the string is greather than the character + * \return true if it is the case + * + * \param character Single character + */ + bool String::operator>(char character) const { if (m_sharedString->size == 0) @@ -3714,6 +4913,13 @@ namespace Nz return m_sharedString->string[0] > character; } + /*! + * \brief Checks whether the string is greather than the "C string" + * \return true if it is the case + * + * \param string String to compare + */ + bool String::operator>(const char* string) const { if (m_sharedString->size == 0) @@ -3725,6 +4931,13 @@ namespace Nz return std::strcmp(GetConstBuffer(), string) > 0; } + /*! + * \brief Checks whether the string is greather than the std::string + * \return true if it is the case + * + * \param string String to compare + */ + bool String::operator>(const std::string& string) const { if (m_sharedString->size == 0) @@ -3736,6 +4949,13 @@ namespace Nz return std::strcmp(GetConstBuffer(), string.c_str()) > 0; } + /*! + * \brief Checks whether the string is greather or equal than the character + * \return true if it is the case + * + * \param character Single character + */ + bool String::operator>=(char character) const { if (character == '\0') @@ -3747,6 +4967,13 @@ namespace Nz return m_sharedString->string[0] > character || (m_sharedString->string[0] == character && m_sharedString->size == 1); } + /*! + * \brief Checks whether the string is greather or equal than the "C string" + * \return true if it is the case + * + * \param string String to compare + */ + bool String::operator>=(const char* string) const { if (!string || !string[0]) @@ -3758,6 +4985,13 @@ namespace Nz return std::strcmp(GetConstBuffer(), string) >= 0; } + /*! + * \brief Checks whether the string is greather or equal than the std::string + * \return true if it is the case + * + * \param string String to compare + */ + bool String::operator>=(const std::string& string) const { if (string.empty()) @@ -3769,6 +5003,13 @@ namespace Nz return std::strcmp(GetConstBuffer(), string.c_str()) >= 0; } + /*! + * \brief Converts the boolean to string + * \return String representation of the boolean + * + * \param boolean Boolean value + */ + String String::Boolean(bool boolean) { std::size_t size = (boolean) ? 4 : 5; @@ -3779,6 +5020,14 @@ namespace Nz return String(std::move(str)); } + /*! + * \brief Lexicographically compares the string + * \return The expected result + * + * \param first First string to use for comparison + * \parma second Second string to use for comparison + */ + int String::Compare(const String& first, const String& second) { if (first.m_sharedString->size == 0) @@ -3790,6 +5039,13 @@ namespace Nz return std::strcmp(first.GetConstBuffer(), second.GetConstBuffer()); } + /*! + * \brief Converts the number to string + * \return String representation of the number + * + * \param number Float value + */ + String String::Number(float number) { std::ostringstream oss; @@ -3799,6 +5055,13 @@ namespace Nz return String(oss.str()); } + /*! + * \brief Converts the number to string + * \return String representation of the number + * + * \param number Double value + */ + String String::Number(double number) { std::ostringstream oss; @@ -3808,6 +5071,13 @@ namespace Nz return String(oss.str()); } + /*! + * \brief Converts the number to string + * \return String representation of the number + * + * \param number Long double value + */ + String String::Number(long double number) { std::ostringstream oss; @@ -3817,56 +5087,143 @@ namespace Nz return String(oss.str()); } + /*! + * \brief Converts the number to string + * \return String representation of the number + * + * \param number Signed char value + * \param radix Base of the number + */ + String String::Number(signed char number, UInt8 radix) { return NumberToString(number, radix); } + /*! + * \brief Converts the number to string + * \return String representation of the number + * + * \param number Unsigned char value + * \param radix Base of the number + */ + String String::Number(unsigned char number, UInt8 radix) { return NumberToString(number, radix); } + /*! + * \brief Converts the number to string + * \return String representation of the number + * + * \param number Short value + * \param radix Base of the number + */ + String String::Number(short number, UInt8 radix) { return NumberToString(number, radix); } + /*! + * \brief Converts the number to string + * \return String representation of the number + * + * \param number Unsigned short value + * \param radix Base of the number + */ + String String::Number(unsigned short number, UInt8 radix) { return NumberToString(number, radix); } + /*! + * \brief Converts the number to string + * \return String representation of the number + * + * \param number Int value + * \param radix Base of the number + */ + String String::Number(int number, UInt8 radix) { return NumberToString(number, radix); } + /*! + * \brief Converts the number to string + * \return String representation of the number + * + * \param number Unsigned int value + * \param radix Base of the number + */ + String String::Number(unsigned int number, UInt8 radix) { return NumberToString(number, radix); } + /*! + * \brief Converts the number to string + * \return String representation of the number + * + * \param number Long value + * \param radix Base of the number + */ + String String::Number(long number, UInt8 radix) { return NumberToString(number, radix); } + /*! + * \brief Converts the number to string + * \return String representation of the number + * + * \param number Unsigned long value + * \param radix Base of the number + */ + String String::Number(unsigned long number, UInt8 radix) { return NumberToString(number, radix); } + /*! + * \brief Converts the number to string + * \return String representation of the number + * + * \param number Long long value + * \param radix Base of the number + */ + String String::Number(long long number, UInt8 radix) { return NumberToString(number, radix); } + /*! + * \brief Converts the number to string + * \return String representation of the number + * + * \param number Unsigned long long value + * \param radix Base of the number + */ + String String::Number(unsigned long long number, UInt8 radix) { return NumberToString(number, radix); } + /*! + * \brief Converts the pointer to string + * \return String representation of the pointer + * + * \param ptr Pointer to represent + */ + String String::Pointer(const void* ptr) { const std::size_t capacity = sizeof(void*)*2 + 2; @@ -3877,6 +5234,13 @@ namespace Nz return String(std::move(str)); } + /*! + * \brief Converts the unicode point to string + * \return String representation of the unicode point + * + * \param character Unicode point + */ + String String::Unicode(char32_t character) { if (character == '\0') @@ -3898,11 +5262,25 @@ namespace Nz return String(std::move(str)); } + /*! + * \brief Converts the unicode "C string" to string + * \return String representation of the unicode "C string" + * + * \param u8String String in UTF-8 + */ + String String::Unicode(const char* u8String) { return String(u8String); } + /*! + * \brief Converts the unicode "C string" to string + * \return String representation of the unicode "C string" + * + * \param u16String String in UTF-16 + */ + String String::Unicode(const char16_t* u16String) { if (!u16String || !u16String[0]) @@ -3914,7 +5292,7 @@ namespace Nz count++; while (*++ptr); - count *= 2; // On s'assure d'avoir la place suffisante + count *= 2; // We ensure to have enough place auto str = std::make_shared(count); @@ -3926,6 +5304,13 @@ namespace Nz return String(std::move(str)); } + /*! + * \brief Converts the unicode "C string" to string + * \return String representation of the unicode "C string" + * + * \param u32String String in UTF-32 + */ + String String::Unicode(const char32_t* u32String) { if (!u32String || !u32String[0]) @@ -3953,6 +5338,13 @@ namespace Nz return String(std::move(str)); } + /*! + * \brief Converts the unicode "C string" to string + * \return String representation of the unicode "C string" + * + * \param wString String in Wide + */ + String String::Unicode(const wchar_t* wString) { if (!wString || !wString[0]) @@ -3980,6 +5372,14 @@ namespace Nz return String(std::move(str)); } + /*! + * \brief Inputs the stream into the string + * \return A reference to the stream + * + * \param is Stream to get information from + * \param str String to set value + */ + std::istream& operator>>(std::istream& is, String& str) { str.Clear(); @@ -4004,6 +5404,14 @@ namespace Nz return is; } + /*! + * \brief Output operator + * \return The stream + * + * \param out The stream + * \param str The string to output + */ + std::ostream& operator<<(std::ostream& os, const String& str) { if (str.IsEmpty()) @@ -4012,6 +5420,14 @@ namespace Nz return operator<<(os, str.m_sharedString->string.get()); } + /*! + * \brief Concatenates the character to the string + * \return String which is the result of the concatenation + * + * \param character Single character + * \param string String in the right hand side + */ + String operator+(char character, const String& string) { if (character == '\0') @@ -4027,6 +5443,14 @@ namespace Nz return String(std::move(str)); } + /*! + * \brief Concatenates the "C string" to the string + * \return String which is the result of the concatenation + * + * \param string String to add + * \param string String in the right hand side + */ + String operator+(const char* string, const String& nstring) { if (!string || !string[0]) @@ -4045,6 +5469,14 @@ namespace Nz return String(std::move(str)); } + /*! + * \brief Concatenates the std::string to the string + * \return String which is the result of the concatenation + * + * \param string String to add + * \param string String in the right hand side + */ + String operator+(const std::string& string, const String& nstring) { if (string.empty()) @@ -4062,6 +5494,14 @@ namespace Nz return String(std::move(str)); } + /*! + * \brief Checks whether the first string is equal to the second string + * \return true if it is the case + * + * \param first String to compare in left hand side + * \param second String to compare in right hand side + */ + bool operator==(const String& first, const String& second) { if (first.m_sharedString->size == 0 || second.m_sharedString->size == 0) @@ -4076,11 +5516,27 @@ namespace Nz return std::strcmp(first.GetConstBuffer(), second.GetConstBuffer()) == 0; } + /*! + * \brief Checks whether the first string is equal to the second string + * \return false if it is the case + * + * \param first String to compare in left hand side + * \param second String to compare in right hand side + */ + bool operator!=(const String& first, const String& second) { return !operator==(first, second); } + /*! + * \brief Checks whether the first string is less than the second string + * \return true if it is the case + * + * \param first String to compare in left hand side + * \param second String to compare in right hand side + */ + bool operator<(const String& first, const String& second) { if (second.m_sharedString->size == 0) @@ -4092,111 +5548,285 @@ namespace Nz return std::strcmp(first.GetConstBuffer(), second.GetConstBuffer()) < 0; } + /*! + * \brief Checks whether the first string is less or equal than the second string + * \return true if it is the case + * + * \param first String to compare in left hand side + * \param second String to compare in right hand side + */ + bool operator<=(const String& first, const String& second) { return !operator<(second, first); } + /*! + * \brief Checks whether the first string is greather than the second string + * \return true if it is the case + * + * \param first String to compare in left hand side + * \param second String to compare in right hand side + */ + bool operator>(const String& first, const String& second) { return second < first; } + /*! + * \brief Checks whether the first string is greather or equal than the second string + * \return true if it is the case + * + * \param first String to compare in left hand side + * \param second String to compare in right hand side + */ + bool operator>=(const String& first, const String& second) { return !operator<(first, second); } + /*! + * \brief Checks whether the string is equal to the character + * \return true if it is the case + * + * \param character Single character in left hand side + * \param second String to compare in right hand side + */ + bool operator==(char character, const String& nstring) { return nstring == character; } + /*! + * \brief Checks whether the string is equal to the "C string" + * \return true if it is the case + * + * \param string String to compare in left hand side + * \param second String to compare in right hand side + */ + bool operator==(const char* string, const String& nstring) { return nstring == string; } + /*! + * \brief Checks whether the string is equal to the std::string + * \return true if it is the case + * + * \param string String to compare in left hand side + * \param second String to compare in right hand side + */ + bool operator==(const std::string& string, const String& nstring) { return nstring == string; } + /*! + * \brief Checks whether the string is equal to the character + * \return false if it is the case + * + * \param character Single character in left hand side + * \param second String to compare in right hand side + */ + bool operator!=(char character, const String& nstring) { return !operator==(character, nstring); } + /*! + * \brief Checks whether the string is equal to the "C string" + * \return false if it is the case + * + * \param string String to compare in left hand side + * \param second String to compare in right hand side + */ + bool operator!=(const char* string, const String& nstring) { return !operator==(string, nstring); } + /*! + * \brief Checks whether the string is equal to the std::string + * \return true if it is the case + * + * \param string String to compare in left hand side + * \param second String to compare in right hand side + */ + bool operator!=(const std::string& string, const String& nstring) { return !operator==(string, nstring); } + /*! + * \brief Checks whether the string is less than the character + * \return true if it is the case + * + * \param character Single character in left hand side + * \param second String to compare in right hand side + */ + bool operator<(char character, const String& nstring) { return nstring > character; } + /*! + * \brief Checks whether the string is less than the "C string" + * \return true if it is the case + * + * \param string String to compare in left hand side + * \param second String to compare in right hand side + */ + bool operator<(const char* string, const String& nstring) { return nstring > string; } + /*! + * \brief Checks whether the string is less than the std::string + * \return true if it is the case + * + * \param string String to compare in left hand side + * \param second String to compare in right hand side + */ + bool operator<(const std::string& string, const String& nstring) { return nstring > string; } + /*! + * \brief Checks whether the string is less or equal than the character + * \return true if it is the case + * + * \param character Single character in left hand side + * \param second String to compare in right hand side + */ + bool operator<=(char character, const String& nstring) { return !operator<(nstring, String(character)); } + /*! + * \brief Checks whether the string is less or equal than the "C string" + * \return true if it is the case + * + * \param string String to compare in left hand side + * \param second String to compare in right hand side + */ + bool operator<=(const char* string, const String& nstring) { return !operator<(nstring, string); } + /*! + * \brief Checks whether the string is less or equal than the std::string + * \return true if it is the case + * + * \param string String to compare in left hand side + * \param second String to compare in right hand side + */ + bool operator<=(const std::string& string, const String& nstring) { return !operator<(nstring, string); } + /*! + * \brief Checks whether the string is greather than the character + * \return true if it is the case + * + * \param character Single character in left hand side + * \param second String to compare in right hand side + */ + bool operator>(char character, const String& nstring) { return nstring < character; } + /*! + * \brief Checks whether the string is greather than the "C string" + * \return true if it is the case + * + * \param string String to compare in left hand side + * \param second String to compare in right hand side + */ + bool operator>(const char* string, const String& nstring) { return nstring < string; } + /*! + * \brief Checks whether the string is greather than the std::string + * \return true if it is the case + * + * \param string String to compare in left hand side + * \param second String to compare in right hand side + */ + bool operator>(const std::string& string, const String& nstring) { return nstring < string; } + /*! + * \brief Checks whether the string is greather or equal than the character + * \return true if it is the case + * + * \param character Single character in left hand side + * \param second String to compare in right hand side + */ + bool operator>=(char character, const String& nstring) { return !operator<(character, nstring); } + /*! + * \brief Checks whether the string is greather or equal than the "C string" + * \return true if it is the case + * + * \param string String to compare in left hand side + * \param second String to compare in right hand side + */ + bool operator>=(const char* string, const String& nstring) { return !operator<(string, nstring); } + /*! + * \brief Checks whether the string is greather or equal than the std::string + * \return true if it is the case + * + * \param string String to compare in left hand side + * \param second String to compare in right hand side + */ + bool operator>=(const std::string& string, const String& nstring) { return !operator<(string, nstring); } + /*! + * \brief Ensures the ownership of the string + * + * \param discardContent Should discard the content + */ + void String::EnsureOwnership(bool discardContent) { if (!m_sharedString) @@ -4212,12 +5842,25 @@ namespace Nz } } + /*! + * \brief Gets the empty string + * \return A reference to the empty string + */ + const std::shared_ptr& String::GetEmptyString() { static auto emptyString = std::make_shared(); return emptyString; } + /*! + * \brief Serializes the string + * \return true if successful + * + * \param context Context of serialization + * \param string String to serialize + */ + bool Serialize(SerializationContext& context, const String& string) { if (!Serialize(context, string.GetSize())) @@ -4226,6 +5869,14 @@ namespace Nz return context.stream->Write(string.GetConstBuffer(), string.GetSize()) == string.GetSize(); } + /*! + * \brief Unserializes the string + * \return true if successful + * + * \param context Context of unserialization + * \param string String to unserialize + */ + bool Unserialize(SerializationContext& context, String* string) { UInt32 size; @@ -4241,6 +5892,14 @@ namespace Nz namespace std { + /*! + * \brief Gets the line from the input stream + * \return A reference to the stream + * + * \param is Input stream to get information from + * \param str String to set + */ + istream& getline(istream& is, Nz::String& str) { str.Clear(); @@ -4248,7 +5907,7 @@ namespace std char c; for (;;) - { + { is.get(c); if (c != '\n' && c != '\0') str += c; @@ -4259,6 +5918,15 @@ namespace std return is; } + /*! + * \brief Gets the line from the input stream + * \return A reference to the stream + * + * \param is Input stream to get information from + * \param str String to set + * \param delim Delimitor defining the end + */ + istream& getline(istream& is, Nz::String& str, char delim) { str.Clear(); @@ -4277,6 +5945,13 @@ namespace std return is; } + /*! + * \brief Swaps two strings, specialisation of std + * + * \param lhs First string + * \param rhs Second string + */ + void swap(Nz::String& lhs, Nz::String& rhs) { lhs.Swap(rhs); diff --git a/src/Nazara/Core/StringStream.cpp b/src/Nazara/Core/StringStream.cpp index 2c2a8db24..a76dc9d86 100644 --- a/src/Nazara/Core/StringStream.cpp +++ b/src/Nazara/Core/StringStream.cpp @@ -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(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(); diff --git a/src/Nazara/Core/TaskScheduler.cpp b/src/Nazara/Core/TaskScheduler.cpp index 27d071987..108e120b1 100644 --- a/src/Nazara/Core/TaskScheduler.cpp +++ b/src/Nazara/Core/TaskScheduler.cpp @@ -24,16 +24,39 @@ namespace Nz unsigned int s_workerCount = 0; } + /*! + * \class Nz::TaskScheduler + * \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()) diff --git a/src/Nazara/Core/Thread.cpp b/src/Nazara/Core/Thread.cpp index 105067baf..da01025d3 100644 --- a/src/Nazara/Core/Thread.cpp +++ b/src/Nazara/Core/Thread.cpp @@ -21,17 +21,36 @@ namespace Nz { + /*! + * \class Nz::Thread + * \brief Core class that represents a thread + */ + + /*! + * \brief Constructs a Thread object by default + */ + Thread::Thread() : m_impl(nullptr) { } + /*! + * \brief Constructs a Thread 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 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; diff --git a/src/Nazara/Core/Unicode.cpp b/src/Nazara/Core/Unicode.cpp index c5b0d6917..9168e855e 100644 --- a/src/Nazara/Core/Unicode.cpp +++ b/src/Nazara/Core/Unicode.cpp @@ -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 -#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') diff --git a/src/Nazara/Utility/X11/Display.cpp b/src/Nazara/Utility/X11/Display.cpp index 2ec41ff0d..63fbb65ac 100644 --- a/src/Nazara/Utility/X11/Display.cpp +++ b/src/Nazara/Utility/X11/Display.cpp @@ -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) diff --git a/tests/Engine/Core/AbstractHash.cpp b/tests/Engine/Core/AbstractHash.cpp new file mode 100644 index 000000000..bcb47fc33 --- /dev/null +++ b/tests/Engine/Core/AbstractHash.cpp @@ -0,0 +1,27 @@ +#include +#include + +#include + +#include + +SCENARIO("AbstractHash", "[CORE][ABSTRACTHASH]") +{ + GIVEN("The hash SHA512") + { + std::unique_ptr SHA512 = Nz::AbstractHash::Get(Nz::HashType_SHA512); + SHA512->Begin(); + + WHEN("We introduce data") + { + std::array array{ 0, 1, 2, 3 }; + SHA512->Append(array.begin(), array.size()); + + THEN("We ask for the bytearray") + { + Nz::ByteArray byteArray = SHA512->End(); + REQUIRE(byteArray.GetSize() == SHA512->GetDigestLength()); + } + } + } +} diff --git a/tests/Engine/Core/AlgorithmCore.cpp b/tests/Engine/Core/AlgorithmCore.cpp new file mode 100644 index 000000000..8aff5cb24 --- /dev/null +++ b/tests/Engine/Core/AlgorithmCore.cpp @@ -0,0 +1,40 @@ +#include +#include + +#include + +#include + +TEST_CASE("Apply", "[CORE][ALGORITHM]") +{ + SECTION("Apply lambda to two vector2") + { + Nz::Vector2 vector = Nz::Vector2::Unit(); + auto lambda = [](const Nz::Vector2& vec1, const Nz::Vector2& vec2) + { + return vec1 + vec2; + }; + + Nz::Vector2 result = Nz::Apply(lambda, std::make_tuple(vector, vector)); + + REQUIRE(result == (Nz::Vector2::Unit() * 2)); + } + + SECTION("Apply member function to vector2") + { + Nz::Vector2 vector = Nz::Vector2::Unit(); + + int result = Nz::Apply(vector, &Nz::Vector2::Distance, std::make_tuple(vector)); + + REQUIRE(result == 0); + } +} + +TEST_CASE("ComputeHash", "[CORE][ALGORITHM]") +{ + SECTION("Compute hash of '0'") + { + auto result = Nz::ComputeHash(Nz::HashType_SHA512, "1234"); + REQUIRE(result.ToHex().ToUpper() == "D404559F602EAB6FD602AC7680DACBFAADD13630335E951F097AF3900E9DE176B6DB28512F2E000B9D04FBA5133E8B1C6E8DF59DB3A8AB9D60BE4B97CC9E81DB"); + } +} diff --git a/tests/Engine/Core/Bitset.cpp b/tests/Engine/Core/Bitset.cpp new file mode 100644 index 000000000..76c35c886 --- /dev/null +++ b/tests/Engine/Core/Bitset.cpp @@ -0,0 +1,117 @@ +#include +#include + +#include + +SCENARIO("Bitset", "[CORE][BITSET]") +{ + GIVEN("Allocate and constructor") + { + Nz::Bitset<> bitset(3); + + THEN("Capacity is 3 and size is 3") + { + REQUIRE(bitset.GetSize() == 3); + REQUIRE(bitset.GetCapacity() >= 3); + } + } + + GIVEN("Iterator and default constructor") + { + Nz::String anotherDataString("0101"); + Nz::Bitset<> defaultByte; + Nz::Bitset<> anotherData(anotherDataString.GetConstBuffer()); + + WHEN("We assign 'anotherData'") + { + defaultByte = anotherDataString; + REQUIRE(anotherData == defaultByte); + REQUIRE(defaultByte.GetSize() == 4); + REQUIRE(defaultByte.GetCapacity() >= 4); + REQUIRE(anotherData.GetSize() == 4); + REQUIRE(anotherData.GetCapacity() >= 4); + } + } + + GIVEN("Copy and Move constructor") + { + Nz::Bitset<> originalArray(3, true); + + WHEN("We copy") + { + Nz::Bitset<> copyBitset(originalArray); + + THEN("We get a copy") + { + REQUIRE(copyBitset == originalArray); + + AND_WHEN("We modify one") + { + for (auto i = 0; i < copyBitset.GetSize(); ++i) + copyBitset[i] = false; + + THEN("They are no more equal") + { + REQUIRE(copyBitset != originalArray); + REQUIRE(copyBitset == Nz::Bitset<>(3, false)); + } + } + } + } + + WHEN("We move") + { + Nz::Bitset<> moveBitset(std::move(originalArray)); + + THEN("These results are expected") + { + REQUIRE(moveBitset == Nz::Bitset<>(3, true)); + REQUIRE(originalArray.GetCapacity() == 0); + } + } + } + + GIVEN("Three bitsets") + { + Nz::Bitset<> first("01001"); + Nz::Bitset<> second("10110"); + Nz::Bitset<> third; + + WHEN("We swap first and third, then second and third and finally third and first") + { + Nz::Bitset<> oldFirst(first); + Nz::Bitset<> oldSecond(second); + + first.Swap(third); + std::swap(second, third); + third.Swap(first); + + THEN("First and second have been swapped and third is still empty.") + { + REQUIRE(oldFirst == second); + REQUIRE(oldSecond == first); + REQUIRE(third.GetSize() == 0); + } + } + } + + GIVEN("Two bitsets") + { + Nz::Bitset<> first("01001"); + Nz::Bitset<> second("10111"); + + WHEN("We perform operators") + { + Nz::Bitset<> andBitset = first & second; + Nz::Bitset<> orBitset = first | second; + Nz::Bitset<> xorBitset = first ^ second; + + THEN("They should operate as logical operators") + { + REQUIRE(andBitset == Nz::Bitset<>("00001")); + REQUIRE(orBitset == Nz::Bitset<>("11111")); + REQUIRE(xorBitset == Nz::Bitset<>("11110")); + } + } + } +} diff --git a/tests/Engine/Core/MemoryPool.cpp b/tests/Engine/Core/MemoryPool.cpp new file mode 100644 index 000000000..6a3c230c4 --- /dev/null +++ b/tests/Engine/Core/MemoryPool.cpp @@ -0,0 +1,28 @@ +#include +#include + +#include + +SCENARIO("MemoryPool", "[CORE][MEMORYPOOL]") +{ + GIVEN("A MemoryPool to contain one Nz::Vector2") + { + Nz::MemoryPool memoryPool(sizeof(Nz::Vector2), 1, false); + + WHEN("We construct a Nz::Vector2") + { + Nz::Vector2* vector2 = memoryPool.New>(1, 2); + + THEN("Memory is available") + { + vector2->x = 3; + REQUIRE(*vector2 == Nz::Vector2(3, 2)); + } + + THEN("We can destroy the vector2") + { + memoryPool.Delete(vector2); + } + } + } +} diff --git a/tests/Engine/Core/ObjectRef.cpp b/tests/Engine/Core/ObjectRef.cpp new file mode 100644 index 000000000..e44e5f1ff --- /dev/null +++ b/tests/Engine/Core/ObjectRef.cpp @@ -0,0 +1,41 @@ +#include +#include + +#include + +SCENARIO("ObjectRef", "[CORE][OBJECTREF]") +{ + GIVEN("A ObjectRef") + { + Nz::ObjectRef objectRef; + + WHEN("We have two objectRef handling the same object") + { + Nz::Font font; + + objectRef = &font; + Nz::ObjectRef otherRef(&font); + + THEN("Pointers the same") + { + REQUIRE(objectRef.IsValid()); + REQUIRE(otherRef.IsValid()); + } + + objectRef.Reset(nullptr); + } + + WHEN("We assign it to a simple font") + { + Nz::Font font; + + THEN("Release suppress the reference to the object") + { + objectRef.Reset(&font); + objectRef.Release(); + + REQUIRE(!objectRef.IsValid()); + } + } + } +} diff --git a/tests/Engine/Core/ParameterList.cpp b/tests/Engine/Core/ParameterList.cpp new file mode 100644 index 000000000..ef2729833 --- /dev/null +++ b/tests/Engine/Core/ParameterList.cpp @@ -0,0 +1,52 @@ +#include +#include + +#include + +SCENARIO("ParameterList", "[CORE][PARAMETERLIST]") +{ + GIVEN("An empty ParameterList") + { + Nz::ParameterList parameterList; + + WHEN("We add String 'string'") + { + Nz::String string("string"); + parameterList.SetParameter("string", string); + + THEN("We can get it back") + { + Nz::String newString; + REQUIRE(parameterList.GetStringParameter("string", &newString)); + REQUIRE(newString == string); + } + } + + WHEN("We add Float '3.f'") + { + float fl = 3.f; + parameterList.SetParameter("float", fl); + + THEN("We can get it back") + { + float newFl; + REQUIRE(parameterList.GetFloatParameter("float", &newFl)); + REQUIRE(newFl == fl); + } + } + + WHEN("We add Pointer to stack value") + { + int stackValue = 3; + void* ptrToStackValue = &stackValue; // Ugly conversion + parameterList.SetParameter("ptr", ptrToStackValue); + + THEN("We can get it back") + { + void* newPtrToStackValue = nullptr; + REQUIRE(parameterList.GetPointerParameter("ptr", &newPtrToStackValue)); + REQUIRE(newPtrToStackValue == ptrToStackValue); + } + } + } +} diff --git a/tests/Engine/Core/PrimitiveList.cpp b/tests/Engine/Core/PrimitiveList.cpp new file mode 100644 index 000000000..84a39cac2 --- /dev/null +++ b/tests/Engine/Core/PrimitiveList.cpp @@ -0,0 +1,31 @@ +#include +#include + +SCENARIO("PrimitiveList", "[CORE][PRIMITIVELIST]") +{ + GIVEN("An empty PrimitiveList") + { + Nz::PrimitiveList primitiveList; + + WHEN("We add two primitives") + { + float size = 1.f; + unsigned int subdivision = 1; + unsigned int recursionLevel = 1; + Nz::Matrix4f identity = Nz::Matrix4f::Identity(); + + primitiveList.AddCubicSphere(size, subdivision, identity); + primitiveList.AddIcoSphere(size, subdivision, identity); + + THEN("There must be two items") + { + REQUIRE(primitiveList.GetSize() == 2); + } + + THEN("The first one is the cubic sphere") + { + REQUIRE(primitiveList(0).sphere.type == Nz::SphereType_Cubic); + } + } + } +} diff --git a/tests/Engine/Core/RefCounted.cpp b/tests/Engine/Core/RefCounted.cpp new file mode 100644 index 000000000..0201f0beb --- /dev/null +++ b/tests/Engine/Core/RefCounted.cpp @@ -0,0 +1,29 @@ +#include +#include + +SCENARIO("RefCounted", "[CORE][REFCOUNTED]") +{ + GIVEN("A refcounted persistent") + { + Nz::RefCounted refCounted; + REQUIRE(refCounted.IsPersistent() == true); + + WHEN("We add a reference to this persistent object") + { + THEN("Number of references should be one") + { + refCounted.AddReference(); + REQUIRE(refCounted.GetReferenceCount() == 1); + REQUIRE(refCounted.RemoveReference() == false); + } + + AND_THEN("We suppress the reference, object is still alive") + { + refCounted.AddReference(); + REQUIRE(refCounted.IsPersistent()); + REQUIRE(refCounted.RemoveReference() == false); + REQUIRE(refCounted.GetReferenceCount() == 0); + } + } + } +} diff --git a/tests/Engine/Core/Signal.cpp b/tests/Engine/Core/Signal.cpp new file mode 100644 index 000000000..c5582d866 --- /dev/null +++ b/tests/Engine/Core/Signal.cpp @@ -0,0 +1,48 @@ +#include +#include + +struct Incrementer +{ + void increment(int* inc) + { + *inc += 1; + } +}; + +void increment(int* inc) +{ + *inc += 1; +} + +SCENARIO("Signal", "[CORE][SIGNAL]") +{ + GIVEN("A signal") + { + Nz::Signal signal; + + WHEN("We connection different callbacks") + { + auto connection = signal.Connect(increment); + signal.Connect([](int* inc){ *inc += 1; }); + Incrementer incrementer; + signal.Connect(incrementer, &Incrementer::increment); + + THEN("The call of signal with inc = 0 must return 3") + { + int inc = 0; + signal(&inc); + REQUIRE(inc == 3); + } + + AND_THEN("When we disconnect one function, there should be only two listeners") + { + connection.Disconnect(); + REQUIRE(!connection.IsConnected()); + + int inc = 0; + signal(&inc); + REQUIRE(inc == 2); + } + } + } +} diff --git a/tests/Engine/Core/SparsePtr.cpp b/tests/Engine/Core/SparsePtr.cpp new file mode 100644 index 000000000..6979549a3 --- /dev/null +++ b/tests/Engine/Core/SparsePtr.cpp @@ -0,0 +1,47 @@ +#include +#include + +#include + +SCENARIO("SparsePtr", "[CORE][SPARSEPTR]") +{ + GIVEN("A sparse pointer pointing to an array with a stride of 2") + { + std::array arrays{0, 1, 2, 3, 4}; + Nz::SparsePtr sparsePtr(arrays.begin(), 2 * sizeof(int)); + + WHEN("We use operators") + { + THEN("Operator[] with 2 should be 4") + { + REQUIRE(4 == sparsePtr[2]); + } + + THEN("Operator++ and Operator-- should be opposite") + { + ++sparsePtr; + REQUIRE(2 == *sparsePtr); + auto old = sparsePtr++; + REQUIRE(2 == *old); + REQUIRE(4 == *sparsePtr); + + --sparsePtr; + REQUIRE(2 == *sparsePtr); + auto oldMinus = sparsePtr--; + REQUIRE(2 == *oldMinus); + REQUIRE(0 == *sparsePtr); + } + + THEN("Operator+ and operator-") + { + auto offsetTwo = sparsePtr + 2; + REQUIRE(4 == *offsetTwo); + + auto offsetZero = offsetTwo - 2; + REQUIRE(0 == *offsetZero); + + REQUIRE((offsetTwo - offsetZero) == 2); + } + } + } +} diff --git a/tests/Engine/Math/AlgorithmMath.cpp b/tests/Engine/Math/AlgorithmMath.cpp new file mode 100644 index 000000000..01413d902 --- /dev/null +++ b/tests/Engine/Math/AlgorithmMath.cpp @@ -0,0 +1,256 @@ +#include +#include + +TEST_CASE("Approach", "[MATH][ALGORITHM]") +{ + SECTION("Approach 8 with 5 by 2") + { + REQUIRE(Nz::Approach(5, 8, 2) == 7); + } + + SECTION("Approach 5 with 8 by 2") + { + REQUIRE(Nz::Approach(8, 5, 2) == 6); + } + + SECTION("Approach 8 with 8 by 2") + { + REQUIRE(Nz::Approach(8, 8, 2) == 8); + } +} + +TEST_CASE("Clamp", "[MATH][ALGORITHM]") +{ + SECTION("Clamp 8 between 5 and 10") + { + REQUIRE(Nz::Clamp(8, 5, 10) == 8); + } + + SECTION("Clamp 4 between 5 and 10") + { + REQUIRE(Nz::Clamp(4, 5, 10) == 5); + } + + SECTION("Clamp 12 between 5 and 10") + { + REQUIRE(Nz::Clamp(12, 5, 10) == 10); + } +} + +TEST_CASE("CountBits", "[MATH][ALGORITHM]") +{ + SECTION("Number 10 has 2 bits set to 1") + { + REQUIRE(Nz::CountBits(10) == 2); + } + + SECTION("Number 0 has 0 bit set to 1") + { + REQUIRE(Nz::CountBits(0) == 0); + } +} + +TEST_CASE("DegreeToRadian", "[MATH][ALGORITHM]") +{ + SECTION("Convert 45.f degree to radian") + { + REQUIRE(Nz::DegreeToRadian(45.f) == Approx(M_PI / 4)); + } +} + +TEST_CASE("GetNearestPowerOfTwo", "[MATH][ALGORITHM]") +{ + SECTION("Nearest power of two of 0 = 1") + { + REQUIRE(Nz::GetNearestPowerOfTwo(0) == 1); + } + + SECTION("Nearest power of two of 16 = 16") + { + REQUIRE(Nz::GetNearestPowerOfTwo(16) == 16); + } + + SECTION("Nearest power of two of 17 = 32") + { + REQUIRE(Nz::GetNearestPowerOfTwo(17) == 32); + } +} + +TEST_CASE("GetNumberLength", "[MATH][ALGORITHM]") +{ + SECTION("GetNumberLength of -127 signed char") + { + signed char minus127 = -127; + REQUIRE(Nz::GetNumberLength(minus127) == 4); + } + + SECTION("GetNumberLength of 255 unsigned char") + { + unsigned char plus255 = 255; + REQUIRE(Nz::GetNumberLength(plus255) == 3); + } + + SECTION("GetNumberLength of -1270 signed int") + { + signed int minus1270 = -1270; + REQUIRE(Nz::GetNumberLength(minus1270) == 5); + } + + SECTION("GetNumberLength of 2550 unsigned int") + { + unsigned int plus2550 = 2550; + REQUIRE(Nz::GetNumberLength(plus2550) == 4); + } + + SECTION("GetNumberLength of -1270 signed long long") + { + signed long long minus12700 = -12700; + REQUIRE(Nz::GetNumberLength(minus12700) == 6); + } + + SECTION("GetNumberLength of 2550 unsigned long long") + { + unsigned long long plus25500 = 25500; + REQUIRE(Nz::GetNumberLength(plus25500) == 5); + } + + SECTION("GetNumberLength of -2.456f float") + { + float minus2P456 = -2.456f; + REQUIRE(Nz::GetNumberLength(minus2P456, 3) == 6); + } + + SECTION("GetNumberLength of -2.456 double") + { + double minus2P456 = -2.456; + REQUIRE(Nz::GetNumberLength(minus2P456, 3) == 6); + } + + SECTION("GetNumberLength of -2.456 long double") + { + long double minus2P456 = -2.456L; + REQUIRE(Nz::GetNumberLength(minus2P456, 3) == 6); + } +} + +TEST_CASE("IntegralLog2", "[MATH][ALGORITHM]") +{ + SECTION("According to implementation, log in base 2 of 0 = 0") + { + REQUIRE(Nz::IntegralLog2(0) == 0); + } + + SECTION("Log in base 2 of 1 = 0") + { + REQUIRE(Nz::IntegralLog2(1) == 0); + } + + SECTION("Log in base 2 of 4 = 2") + { + REQUIRE(Nz::IntegralLog2(4) == 2); + } + + SECTION("Log in base 2 of 5 = 2") + { + REQUIRE(Nz::IntegralLog2(5) == 2); + } +} + +TEST_CASE("IntegralLog2Pot", "[MATH][ALGORITHM]") +{ + SECTION("According to implementation, log in base 2 of 0 = 0") + { + REQUIRE(Nz::IntegralLog2Pot(0) == 0); + } + + SECTION("Log in base 2 of 1 = 0") + { + REQUIRE(Nz::IntegralLog2Pot(1) == 0); + } + + SECTION("Log in base 2 of 4 = 2") + { + REQUIRE(Nz::IntegralLog2Pot(4) == 2); + } +} + +TEST_CASE("IntegralPow", "[MATH][ALGORITHM]") +{ + SECTION("2 to power 4") + { + REQUIRE(Nz::IntegralPow(2, 4) == 16); + } +} + +TEST_CASE("Lerp", "[MATH][ALGORITHM]") +{ + SECTION("Lerp 2 to 6 with 0.5") + { + REQUIRE(Nz::Lerp(2, 6, 0.5) == 4); + } +} + +TEST_CASE("MultiplyAdd", "[MATH][ALGORITHM]") +{ + SECTION("2 * 3 + 1") + { + REQUIRE(Nz::MultiplyAdd(2, 3, 1) == 7); + } +} + +TEST_CASE("NumberEquals", "[MATH][ALGORITHM]") +{ + SECTION("2.35 and 2.351 should be the same at 0.01") + { + CHECK(Nz::NumberEquals(2.35, 2.35, 0.01)); + } + + SECTION("3 and 4 unsigned should be the same at 1") + { + CHECK(Nz::NumberEquals(3U, 4U, 1U)); + } +} + +TEST_CASE("NumberToString", "[MATH][ALGORITHM]") +{ + SECTION("235 to string") + { + REQUIRE(Nz::NumberToString(235) == "235"); + } + + SECTION("-235 to string") + { + REQUIRE(Nz::NumberToString(-235) == "-235"); + } + + SECTION("16 in base 16 to string") + { + REQUIRE(Nz::NumberToString(16, 16) == "10"); + } +} + +TEST_CASE("RadianToDegree", "[MATH][ALGORITHM]") +{ + SECTION("PI / 4 to degree") + { + REQUIRE(Nz::RadianToDegree(M_PI / 4) == Approx(45.f)); + } +} + +TEST_CASE("StringToNumber", "[MATH][ALGORITHM]") +{ + SECTION("235 in string") + { + REQUIRE(Nz::StringToNumber("235") == 235); + } + + SECTION("-235 in string") + { + REQUIRE(Nz::StringToNumber("-235") == -235); + } + + SECTION("16 in base 16 in string") + { + REQUIRE(Nz::StringToNumber("10", 16) == 16); + } +}