From 5e23426b53e79ccc3d1bba0a84051827d9cdc2ee Mon Sep 17 00:00:00 2001 From: krzys-h Date: Sun, 20 Dec 2015 14:24:49 +0100 Subject: [PATCH] Refactored CBotString to use std::string and CBotStringArray to use std::vector --- src/CBot/CBotString.cpp | 278 ++++++----------------------- src/CBot/CBotString.h | 25 ++- src/CBot/CBotStringArray.cpp | 87 +-------- src/CBot/CBotStringArray.h | 12 +- test/unit/CBot/CBotString_test.cpp | 16 -- 5 files changed, 68 insertions(+), 350 deletions(-) diff --git a/src/CBot/CBotString.cpp b/src/CBot/CBotString.cpp index fafcf77a..fc1cefd8 100644 --- a/src/CBot/CBotString.cpp +++ b/src/CBot/CBotString.cpp @@ -25,6 +25,7 @@ #include #include #include +#include //Map is filled with id-string pars that are needed for CBot language parsing const std::map CBotString::s_keywordString = @@ -120,216 +121,97 @@ const std::map CBotString::s_keywordString = CBotString::CBotString() { - m_ptr = nullptr; - m_lg = 0; + m_str = ""; } CBotString::~CBotString() { - delete[] m_ptr; - m_ptr = nullptr; } CBotString::CBotString(const char* p) { - m_lg = strlen(p); + m_str = p; +} - m_ptr = nullptr; - if (m_lg>0) - { - m_ptr = new char[m_lg+1]; - strcpy(m_ptr, p); - } +CBotString::CBotString(const std::string &p) +{ + m_str = p; } CBotString::CBotString(const CBotString& srcString) { - m_lg = srcString.m_lg; - - m_ptr = nullptr; - if (m_lg>0) - { - m_ptr = new char[m_lg+1]; - strcpy(m_ptr, srcString.m_ptr); - } + m_str = srcString.m_str; } - int CBotString::GetLength() { - if (m_ptr == nullptr) return 0; - return strlen( m_ptr ); + return m_str.length(); } CBotString CBotString::Left(int nCount) const { - char chain[2000]; - - // clamp nCount to correct value - if(nCount < 0) nCount = 0; - if(nCount > m_lg) nCount = m_lg; - - int i; - for (i = 0; i < m_lg && i < nCount && i < 1999; ++i) - { - chain[i] = m_ptr[i]; - } - chain[i] = 0 ; - - return CBotString(chain); + return CBotString(m_str.substr(0, nCount)); } CBotString CBotString::Right(int nCount) const { - char chain[2000]; - - // clamp nCount to correct value - if(nCount < 0) nCount = 0; - if(nCount > m_lg) nCount = m_lg; - - int i = m_lg - nCount; - if ( i < 0 ) i = 0; - - int j; - for (j = 0 ; i < m_lg && i < 1999; ++i) - { - chain[j++] = m_ptr[i]; - } - chain[j] = 0 ; - - return CBotString(chain); + return CBotString(m_str.substr(m_str.length()-nCount, std::string::npos)); } 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; + return CBotString(m_str.substr(start, lg)); } int CBotString::Find(const char c) { - for (int i = 0; i < m_lg; ++i) - { - if (m_ptr[i] == c) return i; - } - return -1; + std::size_t pos = m_str.find(c); + return pos != std::string::npos ? pos : -1; } int CBotString::Find(const char * lpsz) { - int l = strlen(lpsz); - - for (size_t i = 0; static_cast(i) <= m_lg-l; ++i) - { - for (size_t j = 0; static_cast(j) < l; ++j) - { - if (m_ptr[i+j] != lpsz[j]) goto bad; - } - return i; -bad:; - } - return -1; + std::size_t pos = m_str.find(lpsz); + return pos != std::string::npos ? pos : -1; } int CBotString::ReverseFind(const char c) { - int i; - for (i = m_lg-1; i >= 0; --i) - { - if (m_ptr[i] == c) return i; - } - return -1; + std::size_t pos = m_str.rfind(c); + return pos != std::string::npos ? pos : -1; } int CBotString::ReverseFind(const char * lpsz) { - int i, j; - int l = strlen(lpsz); - - for (i = m_lg-l; i >= 0; --i) - { - for (j = 0; j < l; ++j) - { - if (m_ptr[i+j] != lpsz[j]) goto bad; - } - return i; -bad:; - } - return -1; + std::size_t pos = m_str.rfind(lpsz); + return pos != std::string::npos ? pos : -1; } void CBotString::MakeUpper() { - for (size_t i = 0; static_cast(i) < m_lg && static_cast(i) < 1999 ; ++i) - { - char c = m_ptr[i]; - if ( c >= 'a' && c <= 'z' ) m_ptr[i] = c - 'a' + 'A'; - } + boost::to_upper(m_str); } void CBotString::MakeLower() { - for (size_t i = 0; static_cast(i) < m_lg && static_cast(i) < 1999 ; ++i) - { - char c = m_ptr[i]; - if ( c >= 'A' && c <= 'Z' ) m_ptr[i] = c - 'A' + 'a'; - } + boost::to_lower(m_str); } bool CBotString::LoadString(unsigned int id) { - const char * str = nullptr; - str = MapIdToString(static_cast(id)); - if (m_ptr != nullptr) - delete[] m_ptr; - - m_lg = strlen(str); - m_ptr = nullptr; - if (m_lg > 0) - { - m_ptr = new char[m_lg+1]; - strcpy(m_ptr, str); - return true; - } - return false; + m_str = MapIdToString(static_cast(id)); + return !m_str.empty(); } const CBotString& CBotString::operator=(const CBotString& stringSrc) { - delete[] m_ptr; - m_ptr = nullptr; - - m_lg = stringSrc.m_lg; - - if (m_lg > 0) - { - m_ptr = new char[m_lg+1]; - strcpy(m_ptr, stringSrc.m_ptr); - } - + m_str = stringSrc.m_str; return *this; } @@ -342,174 +224,114 @@ CBotString CBotString::operator+(const CBotString& stringSrc) const CBotString& CBotString::operator=(const char ch) { - delete[] m_ptr; - - m_lg = 1; - - m_ptr = new char[2]; - m_ptr[0] = ch; - m_ptr[1] = 0; - + m_str = ch; return *this; } const CBotString& CBotString::operator=(const char* pString) { - delete[] m_ptr; - m_ptr = nullptr; - if (pString != nullptr) - { - m_lg = strlen(pString); - - if (m_lg != 0) - { - m_ptr = new char[m_lg+1]; - strcpy(m_ptr, pString); - } - } - + m_str = pString; + else + m_str.clear(); return *this; } const CBotString& CBotString::operator+=(const char ch) { - char* p = new char[m_lg+2]; - - if (m_ptr != nullptr) strcpy(p, m_ptr); - p[m_lg++] = ch; - p[m_lg] = 0; - - delete[] m_ptr; - - m_ptr = p; - + m_str += ch; return *this; } const CBotString& CBotString::operator+=(const CBotString& str) { - char* p = new char[m_lg+str.m_lg+1]; - - //-- 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; - - //-- 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; - - delete[] m_ptr; - - m_ptr = p; - + m_str += str.m_str; return *this; } bool CBotString::operator==(const CBotString& str) { - return Compare(str) == 0; + return m_str == str.m_str; } bool CBotString::operator==(const char* p) { - return Compare(p) == 0; + return m_str == p; } bool CBotString::operator!=(const CBotString& str) { - return Compare(str) != 0; + return m_str != str.m_str; } bool CBotString::operator!=(const char* p) { - return Compare(p) != 0; + return m_str != p; } bool CBotString::operator>(const CBotString& str) { - return Compare(str) > 0; + return m_str > str.m_str; } bool CBotString::operator>(const char* p) { - return Compare(p) > 0; + return m_str > p; } bool CBotString::operator>=(const CBotString& str) { - return Compare(str) >= 0; + return m_str >= str.m_str; } bool CBotString::operator>=(const char* p) { - return Compare(p) >= 0; + return m_str >= p; } bool CBotString::operator<(const CBotString& str) { - return Compare(str) < 0; + return m_str < str.m_str; } bool CBotString::operator<(const char* p) { - return Compare(p) < 0; + return m_str < p; } bool CBotString::operator<=(const CBotString& str) { - return Compare(str) <= 0; + return m_str <= str.m_str; } bool CBotString::operator<=(const char* p) { - return Compare(p) <= 0; + return m_str <= p; } bool CBotString::IsEmpty() const { - return (m_lg == 0); + return m_str.empty(); } void CBotString::Empty() { - delete[] m_ptr; - m_ptr = nullptr; - m_lg = 0; + m_str.clear(); } -static char emptyString[] = {0}; +static char emptyString[] = ""; CBotString::operator const char * () const { - if (this == nullptr || m_ptr == nullptr) return emptyString; - return m_ptr; + if (this == nullptr) return emptyString; // TODO: can this be removed? + return m_str.c_str(); } const char* CBotString::CStr() const { - if (this == nullptr || m_ptr == nullptr) - { - return emptyString; - } - return m_ptr; -} - -int CBotString::Compare(const char * lpsz) const -{ - char* p = m_ptr; - if (lpsz == nullptr) lpsz = emptyString; - if (m_ptr == nullptr) p = emptyString; - return strcmp(p, lpsz); // wcscmp + if (this == nullptr) return emptyString; // TODO: can this be removed? + return m_str.c_str(); } const char * CBotString::MapIdToString(EID id) diff --git a/src/CBot/CBotString.h b/src/CBot/CBotString.h index 3d87d2c0..1628e07e 100644 --- a/src/CBot/CBotString.h +++ b/src/CBot/CBotString.h @@ -31,13 +31,14 @@ /** * \brief CBotString Class used to work on strings + * TODO: do not use this class, code should be refactored to use std::string instead */ class CBotString { public: /** - * \brief CBotString Default constructor. + * \brief CBotString Creates an empty string */ CBotString(); @@ -47,6 +48,12 @@ public: */ CBotString(const char* p); + /** + * \brief CBotString + * \param p + */ + CBotString(const std::string& p); + /** * \brief CBotString * \param p @@ -145,15 +152,6 @@ public: */ 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. */ @@ -198,11 +196,8 @@ public: private: - //! \brief Pointer to string - char* m_ptr; - - //! \brief Length of the string - int m_lg; + //! \brief String + std::string m_str; //! \brief Keeps the string corresponding to keyword ID static const std::map s_keywordString; diff --git a/src/CBot/CBotStringArray.cpp b/src/CBot/CBotStringArray.cpp index add32492..759aa6ae 100644 --- a/src/CBot/CBotStringArray.cpp +++ b/src/CBot/CBotStringArray.cpp @@ -17,112 +17,35 @@ * along with this program. If not, see http://gnu.org/licenses */ -// Modules inlcude #include "CBot/CBotStringArray.h" -#include "CBot/CBotUtils.h" - -// Local include - -// Global include - -// Forward declaration -#include - //////////////////////////////////////////////////////////////////////////////// CBotStringArray::CBotStringArray() { - m_pData = nullptr; - m_nSize = m_nMaxSize = 0; } //////////////////////////////////////////////////////////////////////////////// CBotStringArray::~CBotStringArray() { - SetSize(0); // destroys data ! + m_data.clear(); // destroys data ! } //////////////////////////////////////////////////////////////////////////////// int CBotStringArray::GetSize() { - return m_nSize; + return m_data.size(); } //////////////////////////////////////////////////////////////////////////////// void CBotStringArray::Add(const CBotString& str) { - SetSize(m_nSize+1); - - m_pData[m_nSize-1] = str; + m_data.push_back(str); } //////////////////////////////////////////////////////////////////////////////// void CBotStringArray::SetSize(int nNewSize) { - if (nNewSize == 0) - { - // shrink to nothing - - DestructElements(m_pData, m_nSize); - delete[] reinterpret_cast(m_pData); - m_pData = nullptr; - m_nSize = m_nMaxSize = 0; - } - else if (m_pData == nullptr) - { - // create one with exact size - m_pData = reinterpret_cast (new unsigned char[nNewSize * sizeof(CBotString)]); - - ConstructElements(m_pData, nNewSize); - - m_nSize = m_nMaxSize = nNewSize; - } - else if (nNewSize <= m_nMaxSize) - { - // it fits - if (nNewSize > m_nSize) - { - // initialize the new elements - - ConstructElements(&m_pData[m_nSize], nNewSize-m_nSize); - - } - - else if (m_nSize > nNewSize) // destroy the old elements - DestructElements(&m_pData[nNewSize], m_nSize-nNewSize); - - m_nSize = nNewSize; - } - else - { - // otherwise, grow array - int nGrowBy; - { - // heuristically determine growth when nGrowBy == 0 - // (this avoids heap fragmentation in many situations) - nGrowBy = std::min(1024, std::max(4, m_nSize / 8)); - } - int nNewMax; - if (nNewSize < m_nMaxSize + nGrowBy) - nNewMax = m_nMaxSize + nGrowBy; // granularity - else - nNewMax = nNewSize; // no slush - - CBotString* pNewData = reinterpret_cast (new unsigned char[nNewMax * sizeof(CBotString)]); - - // copy new data from old - memcpy(pNewData, m_pData, m_nSize * sizeof(CBotString)); - - // construct remaining elements - ConstructElements(&pNewData[m_nSize], nNewSize-m_nSize); - - - // Get rid of old stuff (note: no destructors called) - delete[] reinterpret_cast(m_pData); - m_pData = pNewData; - m_nSize = nNewSize; - m_nMaxSize = nNewMax; - } + m_data.resize(nNewSize); } //////////////////////////////////////////////////////////////////////////////// @@ -134,5 +57,5 @@ CBotString& CBotStringArray::operator[](int nIndex) //////////////////////////////////////////////////////////////////////////////// CBotString& CBotStringArray::ElementAt(int nIndex) { - return m_pData[nIndex]; + return m_data[nIndex]; } diff --git a/src/CBot/CBotStringArray.h b/src/CBot/CBotStringArray.h index af4e9eff..fb755bec 100644 --- a/src/CBot/CBotStringArray.h +++ b/src/CBot/CBotStringArray.h @@ -19,15 +19,13 @@ #pragma once -// Modules inlcude #include "CBot/CBotString.h" -// Local include - -// Global include +#include /*! * \brief The CBotStringArray class Class used to arrays of strings management. + * TODO: refactor code to use std::vector instead */ class CBotStringArray : public CBotString { @@ -77,9 +75,5 @@ public: private: - //! Number of elements. - int m_nSize; - //! Reserved size. - int m_nMaxSize; - CBotString* m_pData; + std::vector m_data; }; diff --git a/test/unit/CBot/CBotString_test.cpp b/test/unit/CBot/CBotString_test.cpp index 3e6b6da0..c058cfd6 100644 --- a/test/unit/CBot/CBotString_test.cpp +++ b/test/unit/CBot/CBotString_test.cpp @@ -159,22 +159,6 @@ TEST(CBotString_Test, Right) 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