diff --git a/src/CBot/CBotDll.h b/src/CBot/CBotDll.h index bcb02d18..9027dfb0 100644 --- a/src/CBot/CBotDll.h +++ b/src/CBot/CBotDll.h @@ -250,37 +250,146 @@ private: //////////////////////////////////////////////////////////////////////// -// -// as part of MFC CString not used here. -// -// ( all functions are not implemented yet ) - -/** \brief CBotString Class used to work on strings */ +/** + * \brief CBotString Class used to work on strings + */ class CBotString { public: + + /** + * \brief CBotString Default constructor. + */ CBotString(); + + /** + * \brief CBotString + * \param p + */ CBotString(const char* p); + + /** + * \brief CBotString + * \param p + */ CBotString(const CBotString& p); + + /** + * \brief CBotString Destructor. + */ ~CBotString(); - void Empty(); - bool IsEmpty() const; - int GetLength(); - int Find(const char c); - int Find(const char* lpsz); - int ReverseFind(const char c); - int ReverseFind(const char* lpsz); - bool LoadString(unsigned int id); - CBotString Mid(int nFirst, int nCount) const; - CBotString Mid(int nFirst) const; - CBotString Mid(int start, int lg=-1); - CBotString Left(int nCount) const; - CBotString Right(int nCount) const; - int Compare(const char* lpsz) const; - void MakeUpper(); - void MakeLower(); + /** + * \brief Empty Clear the internal string. + */ + void Empty(); + /** + * \brief IsEmpty Check if the string is empty. + * \return True if the sting is empty false otherwise. + */ + bool IsEmpty() const; + + /** + * \brief GetLength Get the string length. + * \return The size of the string. + */ + int GetLength(); + + /** + * \brief Find Find the position of a character in a string starting from + * the beginning of the string. + * \param c The character to find. + * \return The position of the character or -1 if the character was not + * found. + * \see ReverseFind(const char c) + */ + int Find(const char c); + + /** + * \brief Find Find the position of a string in a string starting from the + * beginning of the string. + * \param lpsz The string to find. + * \return The position of the string or -1 if the string was not + * found. + * \see ReverseFind(const char* lpsz) + */ + int Find(const char* lpsz); + + /** + * \brief Find Find the position of a character in a string starting from + * the end of the string. + * \param c The character to find. + * \return The position of the character or -1 if the character was not + * found. + * \see Find(const char c) + */ + int ReverseFind(const char c); + + /** + * \brief Find Find the position of a string in a string starting from the + * end of the string. + * \param lpsz The string to find. + * \return The string of the character or -1 if the string was not + * found. + * \see Find(const char* lpsz) + */ + int ReverseFind(const char* lpsz); + + /** + * \brief LoadString Load the string associate with the id. + * \param id The id to load. + * \return True if the id exist false otherwise. + */ + bool LoadString(unsigned int id); + + /** + * \brief Mid Return a part of a string from a starting index and until + * the end of the string with a limited size. + * \param nFirst The start index of the character in the string. + * \param lg The size limit. Default value is 2000. + * \return The exctracted string. + */ + CBotString Mid(int start, int lg=-1); + + /** + * \brief Left Return a part of a string starting from the left. + * \param nCount The number of character to retreive. + * \return The exctracted string. + */ + CBotString Left(int nCount) const; + + /** + * \brief Right Return a part of a string starting from the right. + * \param nCount The number of character to retreive. + * \return The exctracted string. + */ + CBotString Right(int nCount) const; + + /** + * \brief Compare Compare a given string to an other. + * \param lpsz The string to compare. + * \return 0 if the two string matches. Less than 0 if the current + * string is less than lpsz. Greater than 0 if the current + * string is greater than lpsz. + */ + int Compare(const char* lpsz) const; + + /** + * \brief MakeUpper Uppercase the string. + */ + void MakeUpper(); + + /** + * \brief MakeLower Lowercase the string. + */ + void MakeLower(); + + /** + * @brief CStr Convert the CBotString to a C string. + * @return A C string string. + */ + const char* CStr() const; /** * \brief Overloaded oprators to work on CBotString classes @@ -311,19 +420,19 @@ public: private: - /** \brief Pointer to string */ + //! \brief Pointer to string char* m_ptr; - /** \brief Length of the string */ + //! \brief Length of the string int m_lg; - /** \brief Keeps the string corresponding to keyword ID */ - static const std::map s_keywordString; + //! \brief Keeps the string corresponding to keyword ID + static const std::map s_keywordString; /** - * \brief MapIdToString maps given ID to its string equivalent - * \param id Provided identifier - * \return string if found, else NullString + * \brief MapIdToString Maps given ID to its string equivalent. + * \param id Provided identifier. + * \return String if found, else NullString. */ static const char * MapIdToString(EID id); }; diff --git a/src/CBot/CBotString.cpp b/src/CBot/CBotString.cpp index 5c58c963..a4240b98 100644 --- a/src/CBot/CBotString.cpp +++ b/src/CBot/CBotString.cpp @@ -209,48 +209,29 @@ CBotString CBotString::Right(int nCount) const return CBotString(chain); } -CBotString CBotString::Mid(int nFirst, int nCount) const +CBotString CBotString::Mid(int start, int lg) { - char chain[2000]; + CBotString res; - // clamps nFirst to correct value - if(nFirst < 0) nFirst = 0; - if(nFirst > m_lg) nFirst = m_lg; + if (lg == -1) lg = 2000; - // clamp nCount to correct value - int remaining = m_lg - nFirst; - if(nCount > remaining) nCount = remaining; - if(nCount < 0) nCount = 0; + // clamp start to correct value + if (start < 0) start = 0; + if (start >= m_lg) return res; - int i; - for (i = nFirst; i < m_lg && i < 1999 && i <= nFirst + nCount; ++i) - { - chain[i] = m_ptr[i]; - } - chain[i] = 0 ; + int remaining = m_lg - start; + if (lg > remaining) lg = remaining; + if (lg < 0) lg = 0; - return CBotString(chain); + char* p = new char[m_lg+1]; + strcpy(p, m_ptr+start); + p[lg] = 0; + + res = p; + delete[] p; + return res; } -CBotString CBotString::Mid(int nFirst) const -{ - char chain[2000]; - - // clamp nFirst to correct value - if(nFirst < 0) nFirst = 0; - if(nFirst > m_lg) nFirst = m_lg; - - int i; - for (i = nFirst; i < m_lg && i < 1999 ; ++i) - { - chain[i] = m_ptr[i]; - } - chain[i] = 0 ; - - return CBotString(chain); -} - - int CBotString::Find(const char c) { for (int i = 0; i < m_lg; ++i) @@ -303,29 +284,6 @@ bad:; return -1; } -CBotString CBotString::Mid(int start, int lg) -{ - CBotString res; - - if (lg == -1) lg = 2000; - - // clamp start to correct value - if (start < 0) start = 0; - if (start >= m_lg) return res; - - int remaining = m_lg - start; - if (lg > remaining) lg = remaining; - if (lg < 0) lg = 0; - - char* p = new char[m_lg+1]; - strcpy(p, m_ptr+start); - p[lg] = 0; - - res = p; - delete[] p; - return res; -} - void CBotString::MakeUpper() { for (size_t i = 0; static_cast(i) < m_lg && static_cast(i) < 1999 ; ++i) @@ -453,9 +411,19 @@ const CBotString& CBotString::operator+=(const CBotString& str) { char* p = new char[m_lg+str.m_lg+1]; - strcpy(p, m_ptr); + //-- Check if the pointer is not null befor trying to copy it + if(m_ptr != nullptr) + { + strcpy(p, m_ptr); + } + char* pp = p + m_lg; - strcpy(pp, str.m_ptr); + + //-- Check if the pointer is not null befor trying to copy it + if(str.m_ptr != nullptr) + { + strcpy(pp, str.m_ptr); + } m_lg = m_lg + str.m_lg; @@ -546,6 +514,14 @@ CBotString::operator const char * () const return m_ptr; } +const char* CBotString::CStr() const +{ + if (this == nullptr || m_ptr == nullptr) + { + return emptyString; + } + return m_ptr; +} int CBotString::Compare(const char * lpsz) const { diff --git a/test/unit/CBot/CBotString_test.cpp b/test/unit/CBot/CBotString_test.cpp new file mode 100644 index 00000000..22171c6a --- /dev/null +++ b/test/unit/CBot/CBotString_test.cpp @@ -0,0 +1,415 @@ +/* + * This file is part of the Colobot: Gold Edition source code + * Copyright (C) 2001-2015, Daniel Roux, EPSITEC SA & TerranovaTeam + * http://epsitec.ch; http://colobot.info; http://github.com/colobot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://gnu.org/licenses + */ + +// Modules inlcude +#include "CBot/CBotDll.h" + +// Local include + +// Global include +#include + +/** + * @brief CBotString_Test.Empty Check Empty and IsEmpty functions of class + * CBotString_Test. + */ +TEST(CBotString_Test, Empty) +{ + CBotString str1; + EXPECT_EQ(true, str1.IsEmpty()); + + CBotString str2("qsexrdctfvygbuh"); + EXPECT_EQ(false, str2.IsEmpty()); + str2.Empty(); + EXPECT_EQ(true, str2.IsEmpty()); +} + +/** + * @brief CBotString_Test.Length Check GetLength function of class + * CBotString_Test. + */ +TEST(CBotString_Test, Length) +{ + CBotString str1; + EXPECT_EQ(0, str1.GetLength()); + + CBotString str2("a"); + EXPECT_EQ(1, str2.GetLength()); + + CBotString str3("aaaaa"); + EXPECT_EQ(5, str3.GetLength()); +} + +/** + * @brief CBotString_Test.Find Check find functions of class CBotString_Test + */ +TEST(CBotString_Test, Find) +{ + CBotString str1("a"); + EXPECT_EQ(0, str1.Find('a')); + + CBotString str2("b"); + EXPECT_EQ(-1, str2.Find('a')); + + CBotString str3("bbabb"); + EXPECT_EQ(2, str3.Find('a')); + + CBotString str4("bbAbb"); + EXPECT_EQ(-1, str4.Find('a')); + + CBotString str5("bbAbb"); + EXPECT_EQ(2, str5.Find('A')); + + CBotString str6("test"); + EXPECT_EQ(0, str6.Find("test")); + + CBotString str7("azazdazd"); + EXPECT_EQ(-1, str7.Find("test")); + + CBotString str8("bbtestbb"); + EXPECT_EQ(2, str8.Find("test")); + + CBotString str9("bbTestbb"); + EXPECT_EQ(-1, str9.Find("test")); + + CBotString str10("bbTestbb"); + EXPECT_EQ(2, str10.Find("Test")); +} + +/** + * @brief CBotString_Test.ReverseFind Check find functions of class + * CBotString_Test + */ +TEST(CBotString_Test, ReverseFind) +{ + CBotString str1("a"); + EXPECT_EQ(0, str1.ReverseFind('a')); + + CBotString str2("b"); + EXPECT_EQ(-1, str2.ReverseFind('a')); + + CBotString str3("bbabb"); + EXPECT_EQ(2, str3.ReverseFind('a')); + + CBotString str4("bbAbb"); + EXPECT_EQ(-1, str4.ReverseFind('a')); + + CBotString str5("bbAbb"); + EXPECT_EQ(2, str5.ReverseFind('A')); + + CBotString str6("test"); + EXPECT_EQ(0, str6.ReverseFind("test")); + + CBotString str7("azazdazd"); + EXPECT_EQ(-1, str7.ReverseFind("test")); + + CBotString str8("bbtestbb"); + EXPECT_EQ(2, str8.ReverseFind("test")); + + CBotString str9("bbTestbb"); + EXPECT_EQ(-1, str9.ReverseFind("test")); + + CBotString str10("bbTestbb"); + EXPECT_EQ(2, str10.ReverseFind("Test")); +} + +/** + * @brief CBotString_Test.Mid Check Mid functions of class CBotString_Test + */ +TEST(CBotString_Test, Mid) +{ + CBotString str1("aaaColobot"); + EXPECT_STREQ(str1.Mid(3).CStr(), "Colobot"); + + CBotString str2("aaaColobotaa"); + EXPECT_STREQ(str2.Mid(3,7).CStr(), "Colobot"); +} + +/** + * @brief CBotString_Test.Left Check Left function of class CBotString_Test + */ +TEST(CBotString_Test, Left) +{ + CBotString str1("Colobotaaa"); + EXPECT_STREQ(str1.Left(7).CStr(), "Colobot"); +} + +/** + * @brief CBotString_Test.Right Check Right function of class CBotString_Test + */ +TEST(CBotString_Test, Right) +{ + CBotString str1("aaaColobot"); + EXPECT_STREQ(str1.Right(7).CStr(), "Colobot"); +} + +/** + * @brief CBotString_Test.Compare Check Compare function of class + * CBotString_Test + */ +TEST(CBotString_Test, Compare) +{ + CBotString str1("colobot"); + EXPECT_EQ(0, str1.Compare("colobot")); + + CBotString str2("a"); + EXPECT_GT(0, str2.Compare("colobot")); + + CBotString str3("z"); + EXPECT_LT(0, str3.Compare("colobot")); +} + +/** + * @brief CBotString_Test.MakeUpper Check MakeUpper function of class + * CBotString_Test + */ +TEST(CBotString_Test, MakeUpper) +{ + CBotString str1("colobot"); + str1.MakeUpper(); + EXPECT_STREQ(str1.CStr(), "COLOBOT"); + + CBotString str2("Colobot"); + str2.MakeUpper(); + EXPECT_STREQ(str2.CStr(), "COLOBOT"); +} + +/** + * @brief CBotString_Test.MakeLower Check MakeLower function of class + * CBotString_Test + */ +TEST(CBotString_Test, MakeLower) +{ + CBotString str1("COLOBOT"); + str1.MakeLower(); + EXPECT_STREQ(str1.CStr(), "colobot"); + + CBotString str2("Colobot"); + str2.MakeLower(); + EXPECT_STREQ(str2.CStr(), "colobot"); +} + +/** + * @brief CBotString_Test.operatorEqual Check operator equal of class + * CBotString_Test + */ +TEST(CBotString_Test, operatorEqual) +{ + //-- CBotString + CBotString botStr1; + CBotString botStr2("Colobot"); + + //-- C Character + const char cStr1[2] = "C"; + + //-- C string + const char cStr2[8] = "Colobot"; + + //-- Compare with CBotString + botStr1 = botStr2; + EXPECT_STREQ(botStr1.CStr(), botStr2.CStr()); + + //-- Compare with C character + botStr1 = cStr1[0]; + EXPECT_STREQ(botStr1.CStr(), cStr1); + + //-- Compare with C string + botStr1 = cStr2; + EXPECT_STREQ(botStr1.CStr(), cStr2); + +} + +/** + * @brief CBotString_Test.operatorIsEqual Check operator is equal of class + * CBotString_Test + */ +TEST(CBotString_Test, operatorIsEqual) +{ + //-- CBotString + CBotString botStr1("C"); + CBotString botStr2("C"); + CBotString botStr3("Colobot"); + + //-- C string + const char cStr1[8] = "Colobot"; + const char cStr2[8] = "colobot"; + + EXPECT_EQ(true, (botStr1 == botStr2)); + EXPECT_EQ(false, (botStr1 == botStr3)); + + //-- Compare with C string + EXPECT_EQ(true, (botStr3 == cStr1)); + EXPECT_EQ(false, (botStr3 == cStr2)); +} + +/** + * @brief CBotString_Test.operatorAdd Check operator add of class + * CBotString_Test. + */ +TEST(CBotString_Test, operatorAdd) +{ + //-- CBotString + CBotString botStr1; + CBotString botStr2("C"); + CBotString botStr3("olobot"); + CBotString botStr4("Colobot"); + + //-- C string + const char cStr1[7] = "olobot"; + + botStr1 + botStr2; + botStr1 + botStr3; + EXPECT_STREQ(botStr1.CStr(), botStr4.CStr()); + + botStr1.Empty(); + botStr1 = botStr2 + cStr1; + EXPECT_STREQ(botStr1.CStr(), botStr4.CStr()); + + botStr1.Empty(); + botStr1 += botStr2; + botStr1 += botStr3; + EXPECT_STREQ(botStr1.CStr(), botStr4.CStr()); + + + botStr1.Empty(); + botStr1 += botStr2; + botStr1 += cStr1; + EXPECT_STREQ(botStr1.CStr(), botStr4.CStr()); +} + +/** + * @brief CBotString_Test.operatorDiff Check operator diff of class + * CBotString_Test. + */ +TEST(CBotString_Test, operatorDiff) +{ + //-- CBotString + CBotString botStr1("C"); + CBotString botStr2("C"); + CBotString botStr3("Colobot"); + + //-- C string + const char cStr1[8] = "Colobot"; + const char cStr2[8] = "colobot"; + + EXPECT_EQ(false, (botStr1 != botStr2)); + EXPECT_EQ(true, (botStr1 != botStr3)); + + //-- Compare with C string + EXPECT_EQ(false, (botStr3 != cStr1)); + EXPECT_EQ(true, (botStr3 != cStr2)); +} + +/** + * @brief CBotString_Test.operatorSuperior Check operator superior of class + * CBotString_Test. + */ +TEST(CBotString_Test, operatorSuperior) +{ + //-- CBotString + CBotString botStr1("a"); + CBotString botStr2("z"); + CBotString botStr3("colobot"); + + //-- C string + const char cStr1[2] = "a"; + const char cStr2[2] = "z"; + + EXPECT_EQ(true, (botStr3 > botStr1)); + EXPECT_EQ(false, (botStr3 > botStr2)); + + //-- Compare with C string + EXPECT_EQ(true, (botStr3 > cStr1)); + EXPECT_EQ(false, (botStr3 > cStr2)); +} + +/** + * @brief CBotString_Test.operatorSuperiorOrEqual Check operator superior or + * equa of class CBotString_Test. + */ +TEST(CBotString_Test, operatorSuperiorOrEqual) +{ + //-- CBotString + CBotString botStr1("a"); + CBotString botStr2("z"); + CBotString botStr3("colobot"); + + //-- C string + const char cStr1[2] = "a"; + const char cStr2[2] = "z"; + const char cStr3[8] = "colobot"; + + EXPECT_EQ(true, (botStr3 >= botStr1)); + EXPECT_EQ(false, (botStr3 >= botStr2)); + EXPECT_EQ(true, (botStr3 >= botStr3)); + + //-- Compare with C string + EXPECT_EQ(true, (botStr3 >= cStr1)); + EXPECT_EQ(false, (botStr3 >= cStr2)); + EXPECT_EQ(true, (botStr3 >= cStr3)); +} + +/** + * @brief CBotString_Test.operatorInferior Check operator Inferior of class + * CBotString_Test. + */ +TEST(CBotString_Test, operatorInferior) +{ + //-- CBotString + CBotString botStr1("a"); + CBotString botStr2("z"); + CBotString botStr3("colobot"); + + //-- C string + const char cStr1[2] = "a"; + const char cStr2[2] = "z"; + + EXPECT_EQ(false, (botStr3 < botStr1)); + EXPECT_EQ(true, (botStr3 < botStr2)); + + //-- Compare with C string + EXPECT_EQ(false, (botStr3 < cStr1)); + EXPECT_EQ(true, (botStr3 < cStr2)); +} + +/** + * @brief CBotString_Test.operatorInferiorOrEqual Check operator Inferior or + * equa of class CBotString_Test. + */ +TEST(CBotString_Test, operatorInferiorOrEqual) +{ + //-- CBotString + CBotString botStr1("a"); + CBotString botStr2("z"); + CBotString botStr3("colobot"); + + //-- C string + const char cStr1[2] = "a"; + const char cStr2[2] = "z"; + const char cStr3[8] = "colobot"; + + EXPECT_EQ(false, (botStr3 <= botStr1)); + EXPECT_EQ(true, (botStr3 <= botStr2)); + EXPECT_EQ(true, (botStr3 <= botStr3)); + + //-- Compare with C string + EXPECT_EQ(false, (botStr3 <= cStr1)); + EXPECT_EQ(true, (botStr3 <= cStr2)); + EXPECT_EQ(true, (botStr3 <= cStr3)); +} diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt index f12c3a22..5bdc38a4 100644 --- a/test/unit/CMakeLists.txt +++ b/test/unit/CMakeLists.txt @@ -15,6 +15,7 @@ set(UT_SOURCES math/geometry_test.cpp math/matrix_test.cpp math/vector_test.cpp + CBot/CBotString_test.cpp ${PLATFORM_TESTS} )