2014-10-14 13:11:37 +00:00
|
|
|
/*
|
|
|
|
* This file is part of the Colobot: Gold Edition source code
|
2015-08-22 14:40:02 +00:00
|
|
|
* Copyright (C) 2001-2015, Daniel Roux, EPSITEC SA & TerranovaTeam
|
|
|
|
* http://epsitec.ch; http://colobot.info; http://github.com/colobot
|
2014-10-14 13:11:37 +00:00
|
|
|
*
|
|
|
|
* 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
|
|
|
|
*/
|
2015-08-22 15:51:39 +00:00
|
|
|
|
2012-08-08 20:35:17 +00:00
|
|
|
/////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
//strings management
|
|
|
|
|
|
|
|
#include "CBot.h"
|
|
|
|
|
|
|
|
#include <cstdlib>
|
|
|
|
#include <cstring>
|
|
|
|
#include <algorithm>
|
|
|
|
|
|
|
|
//Map is filled with id-string pars that are needed for CBot language parsing
|
2012-08-12 23:26:36 +00:00
|
|
|
const std::map<EID,const char *> CBotString::s_keywordString =
|
2012-08-08 20:35:17 +00:00
|
|
|
{
|
|
|
|
{ID_IF, "if"},
|
|
|
|
{ID_ELSE, "else"},
|
|
|
|
{ID_WHILE, "while"},
|
|
|
|
{ID_DO, "do"},
|
|
|
|
{ID_FOR, "for"},
|
|
|
|
{ID_BREAK, "break"},
|
|
|
|
{ID_CONTINUE, "continue"},
|
|
|
|
{ID_SWITCH, "switch"},
|
|
|
|
{ID_CASE, "case"},
|
|
|
|
{ID_DEFAULT, "default"},
|
|
|
|
{ID_TRY, "try"},
|
|
|
|
{ID_THROW, "throw"},
|
|
|
|
{ID_CATCH, "catch"},
|
|
|
|
{ID_FINALLY, "finally"},
|
|
|
|
{ID_TXT_AND, "and"},
|
|
|
|
{ID_TXT_OR, "or"},
|
|
|
|
{ID_TXT_NOT, "not"},
|
|
|
|
{ID_RETURN, "return"},
|
|
|
|
{ID_CLASS, "class"},
|
|
|
|
{ID_EXTENDS, "extends"},
|
|
|
|
{ID_SYNCHO, "synchronized"},
|
|
|
|
{ID_NEW, "new"},
|
|
|
|
{ID_PUBLIC, "public"},
|
|
|
|
{ID_EXTERN, "extern"},
|
|
|
|
{ID_STATIC, "static"},
|
|
|
|
{ID_PROTECTED, "protected"},
|
|
|
|
{ID_PRIVATE, "private"},
|
|
|
|
{ID_DEBUGDD, "STARTDEBUGDD"},
|
|
|
|
{ID_INT, "int"},
|
|
|
|
{ID_FLOAT, "float"},
|
|
|
|
{ID_BOOLEAN, "boolean"},
|
|
|
|
{ID_STRING, "string"},
|
|
|
|
{ID_VOID, "void"},
|
|
|
|
{ID_BOOL, "bool"},
|
|
|
|
{ID_TRUE, "true"},
|
|
|
|
{ID_FALSE, "false"},
|
|
|
|
{ID_NULL, "null"},
|
|
|
|
{ID_NAN, "nan"},
|
|
|
|
{ID_OPENPAR, "("},
|
|
|
|
{ID_CLOSEPAR, ")"},
|
|
|
|
{ID_OPBLK, "{"},
|
|
|
|
{ID_CLBLK, "}"},
|
2012-08-09 20:05:42 +00:00
|
|
|
{ID_SEP, ";"},
|
2012-08-08 20:35:17 +00:00
|
|
|
{ID_COMMA, ","},
|
|
|
|
{ID_DOTS, ":"},
|
|
|
|
{ID_DOT, "."},
|
|
|
|
{ID_OPBRK, "["},
|
|
|
|
{ID_CLBRK, "]"},
|
|
|
|
{ID_DBLDOTS, "::"},
|
|
|
|
{ID_LOGIC, "?"},
|
|
|
|
{ID_ADD, "+"},
|
|
|
|
{ID_SUB, "-"},
|
|
|
|
{ID_MUL, "*"},
|
|
|
|
{ID_DIV, "/"},
|
|
|
|
{ID_ASS, "="},
|
|
|
|
{ID_ASSADD, "+="},
|
|
|
|
{ID_ASSSUB, "-="},
|
|
|
|
{ID_ASSMUL, "*="},
|
|
|
|
{ID_ASSDIV, "/="},
|
|
|
|
{ID_ASSOR, "|="},
|
|
|
|
{ID_ASSAND, "&="},
|
|
|
|
{ID_ASSXOR, "^="},
|
|
|
|
{ID_ASSSL, "<<="},
|
|
|
|
{ID_ASSSR, ">>>="},
|
|
|
|
{ID_ASSASR, ">>="},
|
|
|
|
{ID_SL, "<<"},
|
|
|
|
{ID_SR, ">>"},
|
|
|
|
{ID_ASR, ">>"},
|
|
|
|
{ID_INC, "++"},
|
|
|
|
{ID_DEC, "--"},
|
|
|
|
{ID_LO, "<"},
|
|
|
|
{ID_HI, ">"},
|
2012-10-06 22:09:50 +00:00
|
|
|
{ID_LS, "<="},
|
2012-08-08 20:35:17 +00:00
|
|
|
{ID_HS, ">="},
|
|
|
|
{ID_EQ, "=="},
|
|
|
|
{ID_NE, "!="},
|
|
|
|
{ID_AND, "&"},
|
|
|
|
{ID_XOR, "^"},
|
|
|
|
{ID_OR, "|"},
|
|
|
|
{ID_LOG_AND, "&&"},
|
|
|
|
{ID_LOG_OR, "||"},
|
|
|
|
{ID_LOG_NOT, "!"},
|
|
|
|
{ID_NOT, "~"},
|
|
|
|
{ID_MODULO, "%"},
|
|
|
|
{ID_POWER, "**"},
|
|
|
|
{ID_ASSMODULO, "%="},
|
|
|
|
{TX_UNDEF, "undefined"},
|
|
|
|
{TX_NAN, "not a number"}
|
|
|
|
};
|
|
|
|
|
|
|
|
CBotString::CBotString()
|
|
|
|
{
|
2015-08-16 10:43:42 +00:00
|
|
|
m_ptr = nullptr;
|
2012-08-08 20:35:17 +00:00
|
|
|
m_lg = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
CBotString::~CBotString()
|
|
|
|
{
|
2012-12-28 12:37:08 +00:00
|
|
|
delete[] m_ptr;
|
|
|
|
m_ptr = nullptr;
|
2012-08-08 20:35:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CBotString::CBotString(const char* p)
|
|
|
|
{
|
|
|
|
m_lg = strlen(p);
|
|
|
|
|
2015-08-16 10:43:42 +00:00
|
|
|
m_ptr = nullptr;
|
2012-08-08 20:35:17 +00:00
|
|
|
if (m_lg>0)
|
|
|
|
{
|
2012-12-28 12:37:08 +00:00
|
|
|
m_ptr = new char[m_lg+1];
|
2012-08-08 20:35:17 +00:00
|
|
|
strcpy(m_ptr, p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CBotString::CBotString(const CBotString& srcString)
|
|
|
|
{
|
|
|
|
m_lg = srcString.m_lg;
|
|
|
|
|
2015-08-16 10:43:42 +00:00
|
|
|
m_ptr = nullptr;
|
2012-08-08 20:35:17 +00:00
|
|
|
if (m_lg>0)
|
|
|
|
{
|
2012-12-28 12:37:08 +00:00
|
|
|
m_ptr = new char[m_lg+1];
|
2012-08-08 20:35:17 +00:00
|
|
|
strcpy(m_ptr, srcString.m_ptr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-08-11 18:59:35 +00:00
|
|
|
int CBotString::GetLength()
|
2012-08-08 20:35:17 +00:00
|
|
|
{
|
2015-08-16 10:43:42 +00:00
|
|
|
if (m_ptr == nullptr) return 0;
|
2013-05-26 15:47:54 +00:00
|
|
|
return strlen( m_ptr );
|
2012-08-08 20:35:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CBotString CBotString::Left(int nCount) const
|
|
|
|
{
|
|
|
|
char chain[2000];
|
|
|
|
|
2015-05-07 11:53:53 +00:00
|
|
|
// clamp nCount to correct value
|
|
|
|
if(nCount < 0) nCount = 0;
|
|
|
|
if(nCount > m_lg) nCount = m_lg;
|
|
|
|
|
2012-08-12 23:26:36 +00:00
|
|
|
int i;
|
2012-08-08 20:35:17 +00:00
|
|
|
for (i = 0; i < m_lg && i < nCount && i < 1999; ++i)
|
|
|
|
{
|
|
|
|
chain[i] = m_ptr[i];
|
|
|
|
}
|
|
|
|
chain[i] = 0 ;
|
|
|
|
|
|
|
|
return CBotString(chain);
|
|
|
|
}
|
|
|
|
|
|
|
|
CBotString CBotString::Right(int nCount) const
|
|
|
|
{
|
|
|
|
char chain[2000];
|
|
|
|
|
2015-05-07 11:53:53 +00:00
|
|
|
// clamp nCount to correct value
|
|
|
|
if(nCount < 0) nCount = 0;
|
|
|
|
if(nCount > m_lg) nCount = m_lg;
|
|
|
|
|
2012-08-08 20:35:17 +00:00
|
|
|
int i = m_lg - nCount;
|
|
|
|
if ( i < 0 ) i = 0;
|
|
|
|
|
2012-08-12 23:26:36 +00:00
|
|
|
int j;
|
2012-09-22 09:48:41 +00:00
|
|
|
for (j = 0 ; i < m_lg && i < 1999; ++i)
|
2012-08-08 20:35:17 +00:00
|
|
|
{
|
|
|
|
chain[j++] = m_ptr[i];
|
|
|
|
}
|
|
|
|
chain[j] = 0 ;
|
|
|
|
|
|
|
|
return CBotString(chain);
|
|
|
|
}
|
|
|
|
|
2015-11-01 16:03:30 +00:00
|
|
|
CBotString CBotString::Mid(int start, int lg)
|
2012-08-08 20:35:17 +00:00
|
|
|
{
|
2015-11-01 16:03:30 +00:00
|
|
|
CBotString res;
|
2012-08-08 20:35:17 +00:00
|
|
|
|
2015-11-01 16:03:30 +00:00
|
|
|
if (lg == -1) lg = 2000;
|
2012-08-08 20:35:17 +00:00
|
|
|
|
2015-11-01 16:03:30 +00:00
|
|
|
// clamp start to correct value
|
|
|
|
if (start < 0) start = 0;
|
|
|
|
if (start >= m_lg) return res;
|
2012-08-08 20:35:17 +00:00
|
|
|
|
2015-11-01 16:03:30 +00:00
|
|
|
int remaining = m_lg - start;
|
|
|
|
if (lg > remaining) lg = remaining;
|
|
|
|
if (lg < 0) lg = 0;
|
2015-05-07 11:53:53 +00:00
|
|
|
|
2015-11-01 16:03:30 +00:00
|
|
|
char* p = new char[m_lg+1];
|
|
|
|
strcpy(p, m_ptr+start);
|
|
|
|
p[lg] = 0;
|
2012-08-08 20:35:17 +00:00
|
|
|
|
2015-11-01 16:03:30 +00:00
|
|
|
res = p;
|
|
|
|
delete[] p;
|
|
|
|
return res;
|
2012-08-08 20:35:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int CBotString::Find(const char c)
|
|
|
|
{
|
2012-08-12 23:26:36 +00:00
|
|
|
for (int i = 0; i < m_lg; ++i)
|
2012-08-08 20:35:17 +00:00
|
|
|
{
|
|
|
|
if (m_ptr[i] == c) return i;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int CBotString::Find(const char * lpsz)
|
|
|
|
{
|
|
|
|
int l = strlen(lpsz);
|
|
|
|
|
2012-08-12 23:26:36 +00:00
|
|
|
for (size_t i = 0; static_cast<int>(i) <= m_lg-l; ++i)
|
2012-08-08 20:35:17 +00:00
|
|
|
{
|
2012-08-12 23:26:36 +00:00
|
|
|
for (size_t j = 0; static_cast<int>(j) < l; ++j)
|
2012-08-08 20:35:17 +00:00
|
|
|
{
|
|
|
|
if (m_ptr[i+j] != lpsz[j]) goto bad;
|
|
|
|
}
|
|
|
|
return i;
|
|
|
|
bad:;
|
|
|
|
}
|
|
|
|
return -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;
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CBotString::MakeUpper()
|
|
|
|
{
|
2012-08-12 23:26:36 +00:00
|
|
|
for (size_t i = 0; static_cast<int>(i) < m_lg && static_cast<int>(i) < 1999 ; ++i)
|
2012-08-08 20:35:17 +00:00
|
|
|
{
|
|
|
|
char c = m_ptr[i];
|
|
|
|
if ( c >= 'a' && c <= 'z' ) m_ptr[i] = c - 'a' + 'A';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CBotString::MakeLower()
|
|
|
|
{
|
2012-08-12 23:26:36 +00:00
|
|
|
for (size_t i = 0; static_cast<int>(i) < m_lg && static_cast<int>(i) < 1999 ; ++i)
|
2012-08-08 20:35:17 +00:00
|
|
|
{
|
|
|
|
char c = m_ptr[i];
|
|
|
|
if ( c >= 'A' && c <= 'Z' ) m_ptr[i] = c - 'A' + 'a';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CBotString::LoadString(unsigned int id)
|
|
|
|
{
|
2012-12-28 12:37:08 +00:00
|
|
|
const char * str = nullptr;
|
2012-08-12 23:26:36 +00:00
|
|
|
str = MapIdToString(static_cast<EID>(id));
|
2012-12-28 12:37:08 +00:00
|
|
|
if (m_ptr != nullptr)
|
|
|
|
delete[] m_ptr;
|
2012-08-08 20:35:17 +00:00
|
|
|
|
|
|
|
m_lg = strlen(str);
|
2015-08-16 10:43:42 +00:00
|
|
|
m_ptr = nullptr;
|
2012-08-08 20:35:17 +00:00
|
|
|
if (m_lg > 0)
|
|
|
|
{
|
2012-12-28 12:37:08 +00:00
|
|
|
m_ptr = new char[m_lg+1];
|
2012-08-08 20:35:17 +00:00
|
|
|
strcpy(m_ptr, str);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const CBotString& CBotString::operator=(const CBotString& stringSrc)
|
|
|
|
{
|
2012-12-28 12:37:08 +00:00
|
|
|
delete[] m_ptr;
|
|
|
|
m_ptr = nullptr;
|
2012-08-08 20:35:17 +00:00
|
|
|
|
2013-05-26 15:47:54 +00:00
|
|
|
m_lg = stringSrc.m_lg;
|
2012-08-08 20:35:17 +00:00
|
|
|
|
|
|
|
if (m_lg > 0)
|
|
|
|
{
|
2012-12-28 12:37:08 +00:00
|
|
|
m_ptr = new char[m_lg+1];
|
2012-08-08 20:35:17 +00:00
|
|
|
strcpy(m_ptr, stringSrc.m_ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2015-11-02 22:08:52 +00:00
|
|
|
CBotString CBotString::operator+(const CBotString& stringSrc)
|
2012-08-08 20:35:17 +00:00
|
|
|
{
|
2015-11-02 22:08:52 +00:00
|
|
|
CBotString s(*this);
|
|
|
|
s += stringSrc;
|
|
|
|
return s;
|
2012-08-08 20:35:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const CBotString& CBotString::operator=(const char ch)
|
|
|
|
{
|
2012-12-28 12:37:08 +00:00
|
|
|
delete[] m_ptr;
|
2012-08-08 20:35:17 +00:00
|
|
|
|
2013-05-26 15:47:54 +00:00
|
|
|
m_lg = 1;
|
2012-08-08 20:35:17 +00:00
|
|
|
|
2012-12-28 12:37:08 +00:00
|
|
|
m_ptr = new char[2];
|
2012-08-08 20:35:17 +00:00
|
|
|
m_ptr[0] = ch;
|
|
|
|
m_ptr[1] = 0;
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
const CBotString& CBotString::operator=(const char* pString)
|
|
|
|
{
|
2012-12-28 12:37:08 +00:00
|
|
|
delete[] m_ptr;
|
|
|
|
m_ptr = nullptr;
|
2012-08-08 20:35:17 +00:00
|
|
|
|
2012-12-28 12:37:08 +00:00
|
|
|
if (pString != nullptr)
|
2012-08-08 20:35:17 +00:00
|
|
|
{
|
2013-05-26 15:47:54 +00:00
|
|
|
m_lg = strlen(pString);
|
2012-08-08 20:35:17 +00:00
|
|
|
|
|
|
|
if (m_lg != 0)
|
|
|
|
{
|
2012-12-28 12:37:08 +00:00
|
|
|
m_ptr = new char[m_lg+1];
|
2012-08-08 20:35:17 +00:00
|
|
|
strcpy(m_ptr, pString);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const CBotString& CBotString::operator+=(const char ch)
|
|
|
|
{
|
2012-12-28 12:37:08 +00:00
|
|
|
char* p = new char[m_lg+2];
|
2012-08-08 20:35:17 +00:00
|
|
|
|
2012-12-28 12:37:08 +00:00
|
|
|
if (m_ptr != nullptr) strcpy(p, m_ptr);
|
2012-08-08 20:35:17 +00:00
|
|
|
p[m_lg++] = ch;
|
|
|
|
p[m_lg] = 0;
|
|
|
|
|
2012-12-28 12:37:08 +00:00
|
|
|
delete[] m_ptr;
|
2012-08-08 20:35:17 +00:00
|
|
|
|
|
|
|
m_ptr = p;
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
const CBotString& CBotString::operator+=(const CBotString& str)
|
|
|
|
{
|
2012-12-28 12:37:08 +00:00
|
|
|
char* p = new char[m_lg+str.m_lg+1];
|
2012-08-08 20:35:17 +00:00
|
|
|
|
2015-11-01 16:03:30 +00:00
|
|
|
//-- Check if the pointer is not null befor trying to copy it
|
|
|
|
if(m_ptr != nullptr)
|
|
|
|
{
|
|
|
|
strcpy(p, m_ptr);
|
|
|
|
}
|
|
|
|
|
2012-08-08 20:35:17 +00:00
|
|
|
char* pp = p + m_lg;
|
2015-11-01 16:03:30 +00:00
|
|
|
|
|
|
|
//-- Check if the pointer is not null befor trying to copy it
|
|
|
|
if(str.m_ptr != nullptr)
|
|
|
|
{
|
|
|
|
strcpy(pp, str.m_ptr);
|
|
|
|
}
|
2012-08-08 20:35:17 +00:00
|
|
|
|
|
|
|
m_lg = m_lg + str.m_lg;
|
|
|
|
|
2012-12-28 12:37:08 +00:00
|
|
|
delete[] m_ptr;
|
2012-08-08 20:35:17 +00:00
|
|
|
|
|
|
|
m_ptr = p;
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CBotString::operator==(const CBotString& str)
|
|
|
|
{
|
|
|
|
return Compare(str) == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CBotString::operator==(const char* p)
|
|
|
|
{
|
|
|
|
return Compare(p) == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CBotString::operator!=(const CBotString& str)
|
|
|
|
{
|
|
|
|
return Compare(str) != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CBotString::operator!=(const char* p)
|
|
|
|
{
|
|
|
|
return Compare(p) != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CBotString::operator>(const CBotString& str)
|
|
|
|
{
|
|
|
|
return Compare(str) > 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CBotString::operator>(const char* p)
|
|
|
|
{
|
|
|
|
return Compare(p) > 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CBotString::operator>=(const CBotString& str)
|
|
|
|
{
|
|
|
|
return Compare(str) >= 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CBotString::operator>=(const char* p)
|
|
|
|
{
|
|
|
|
return Compare(p) >= 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CBotString::operator<(const CBotString& str)
|
|
|
|
{
|
|
|
|
return Compare(str) < 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CBotString::operator<(const char* p)
|
|
|
|
{
|
|
|
|
return Compare(p) < 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CBotString::operator<=(const CBotString& str)
|
|
|
|
{
|
|
|
|
return Compare(str) <= 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CBotString::operator<=(const char* p)
|
|
|
|
{
|
|
|
|
return Compare(p) <= 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CBotString::IsEmpty() const
|
|
|
|
{
|
|
|
|
return (m_lg == 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CBotString::Empty()
|
|
|
|
{
|
2012-12-28 12:37:08 +00:00
|
|
|
delete[] m_ptr;
|
|
|
|
m_ptr = nullptr;
|
2012-08-08 20:35:17 +00:00
|
|
|
m_lg = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char emptyString[] = {0};
|
|
|
|
|
|
|
|
CBotString::operator const char * () const
|
|
|
|
{
|
2015-08-16 10:43:42 +00:00
|
|
|
if (this == nullptr || m_ptr == nullptr) return emptyString;
|
2012-08-08 20:35:17 +00:00
|
|
|
return m_ptr;
|
|
|
|
}
|
|
|
|
|
2015-11-01 16:03:30 +00:00
|
|
|
const char* CBotString::CStr() const
|
|
|
|
{
|
|
|
|
if (this == nullptr || m_ptr == nullptr)
|
|
|
|
{
|
|
|
|
return emptyString;
|
|
|
|
}
|
|
|
|
return m_ptr;
|
|
|
|
}
|
2012-08-08 20:35:17 +00:00
|
|
|
|
|
|
|
int CBotString::Compare(const char * lpsz) const
|
|
|
|
{
|
|
|
|
char* p = m_ptr;
|
2015-08-16 10:43:42 +00:00
|
|
|
if (lpsz == nullptr) lpsz = emptyString;
|
|
|
|
if (m_ptr == nullptr) p = emptyString;
|
2013-05-26 15:47:54 +00:00
|
|
|
return strcmp(p, lpsz); // wcscmp
|
2012-08-08 20:35:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const char * CBotString::MapIdToString(EID id)
|
|
|
|
{
|
|
|
|
if (s_keywordString.find(id) != s_keywordString.end())
|
|
|
|
{
|
|
|
|
return s_keywordString.at(id);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return emptyString;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// arrays of strings
|
|
|
|
|
|
|
|
CBotStringArray::CBotStringArray()
|
|
|
|
{
|
2015-08-16 10:43:42 +00:00
|
|
|
m_pData = nullptr;
|
2012-08-08 20:35:17 +00:00
|
|
|
m_nSize = m_nMaxSize = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
CBotStringArray::~CBotStringArray()
|
|
|
|
{
|
|
|
|
SetSize(0); // destroys data !
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-11 18:59:35 +00:00
|
|
|
int CBotStringArray::GetSize()
|
2012-08-08 20:35:17 +00:00
|
|
|
{
|
|
|
|
return m_nSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CBotStringArray::Add(const CBotString& str)
|
|
|
|
{
|
|
|
|
SetSize(m_nSize+1);
|
|
|
|
|
|
|
|
m_pData[m_nSize-1] = str;
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
// utility routines
|
|
|
|
|
|
|
|
static inline void ConstructElement(CBotString* pNewData)
|
|
|
|
{
|
|
|
|
memset(pNewData, 0, sizeof(CBotString));
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void DestructElement(CBotString* pOldData)
|
|
|
|
{
|
|
|
|
pOldData->~CBotString();
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void CopyElement(CBotString* pSrc, CBotString* pDest)
|
|
|
|
{
|
|
|
|
*pSrc = *pDest;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ConstructElements(CBotString* pNewData, int nCount)
|
|
|
|
{
|
|
|
|
while (nCount--)
|
|
|
|
{
|
|
|
|
ConstructElement(pNewData);
|
|
|
|
pNewData++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void DestructElements(CBotString* pOldData, int nCount)
|
|
|
|
{
|
|
|
|
while (nCount--)
|
|
|
|
{
|
|
|
|
DestructElement(pOldData);
|
|
|
|
pOldData++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// set the array size
|
|
|
|
|
|
|
|
void CBotStringArray::SetSize(int nNewSize)
|
|
|
|
{
|
|
|
|
if (nNewSize == 0)
|
|
|
|
{
|
|
|
|
// shrink to nothing
|
|
|
|
|
|
|
|
DestructElements(m_pData, m_nSize);
|
2012-09-17 22:01:00 +00:00
|
|
|
delete[] reinterpret_cast<unsigned char *>(m_pData);
|
2015-08-16 10:43:42 +00:00
|
|
|
m_pData = nullptr;
|
2012-08-08 20:35:17 +00:00
|
|
|
m_nSize = m_nMaxSize = 0;
|
|
|
|
}
|
2015-08-16 10:43:42 +00:00
|
|
|
else if (m_pData == nullptr)
|
2012-08-08 20:35:17 +00:00
|
|
|
{
|
|
|
|
// create one with exact size
|
2012-09-17 22:01:00 +00:00
|
|
|
m_pData = reinterpret_cast<CBotString*> (new unsigned char[nNewSize * sizeof(CBotString)]);
|
2012-08-08 20:35:17 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
|
2012-09-17 22:01:00 +00:00
|
|
|
CBotString* pNewData = reinterpret_cast<CBotString*> (new unsigned char[nNewMax * sizeof(CBotString)]);
|
2012-08-08 20:35:17 +00:00
|
|
|
|
|
|
|
// 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)
|
2012-09-17 22:01:00 +00:00
|
|
|
delete[] reinterpret_cast<unsigned char *>(m_pData);
|
2012-08-08 20:35:17 +00:00
|
|
|
m_pData = pNewData;
|
|
|
|
m_nSize = nNewSize;
|
|
|
|
m_nMaxSize = nNewMax;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CBotString& CBotStringArray::operator[](int nIndex)
|
|
|
|
{
|
|
|
|
return ElementAt(nIndex);
|
|
|
|
}
|
|
|
|
|
|
|
|
CBotString& CBotStringArray::ElementAt(int nIndex)
|
|
|
|
{
|
|
|
|
return m_pData[nIndex];
|
|
|
|
}
|