colobot/src/CBot/stdlib/StringFunctions.cpp

305 lines
8.9 KiB
C++

/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2018, 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
*/
#include "CBot/stdlib/stdlib.h"
#include "CBot/CBot.h"
#include "CBot/CBotUtils.h"
#include <boost/algorithm/string.hpp>
namespace CBot
{
namespace
{
////////////////////////////////////////////////////////////////////////////////
bool rStrLen( CBotVar* pVar, CBotVar* pResult, int& ex, void* pUser )
{
// it takes a parameter
if ( pVar == nullptr ) { ex = CBotErrLowParam ; return true; }
// to be a string
if ( pVar->GetType() != CBotTypString ) { ex = CBotErrBadString ; return true; }
// no second parameter
if ( pVar->GetNext() != nullptr ) { ex = CBotErrOverParam ; return true; }
// get the contents of the string
std::string s = pVar->GetValString();
// puts the length of the stack
pResult->SetValInt( s.length() );
return true;
}
////////////////////////////////////////////////////////////////////////////////
bool rStrLeft( CBotVar* pVar, CBotVar* pResult, int& ex, void* pUser )
{
// it takes a parameter
if ( pVar == nullptr ) { ex = CBotErrLowParam ; return true; }
// to be a string
if ( pVar->GetType() != CBotTypString ) { ex = CBotErrBadString ; return true; }
// get the contents of the string
std::string s = pVar->GetValString();
// it takes a second parameter
pVar = pVar->GetNext();
if ( pVar == nullptr ) { ex = CBotErrLowParam ; return true; }
// which must be a number
if ( pVar->GetType() > CBotTypDouble ) { ex = CBotErrBadNum ; return true; }
// retrieves this number
int n = pVar->GetValInt();
if (n > static_cast<int>(s.length())) n = s.length();
if (n < 0) n = 0;
// no third parameter
if ( pVar->GetNext() != nullptr ) { ex = CBotErrOverParam ; return true; }
// takes the interesting part
s = s.substr(0, n);
// puts on the stack
pResult->SetValString( s );
return true;
}
////////////////////////////////////////////////////////////////////////////////
bool rStrRight( CBotVar* pVar, CBotVar* pResult, int& ex, void* pUser )
{
// it takes a parameter
if ( pVar == nullptr ) { ex = CBotErrLowParam ; return true; }
// to be a string
if ( pVar->GetType() != CBotTypString ) { ex = CBotErrBadString ; return true; }
// get the contents of the string
std::string s = pVar->GetValString();
// it takes a second parameter
pVar = pVar->GetNext();
if ( pVar == nullptr ) { ex = CBotErrLowParam ; return true; }
// which must be a number
if ( pVar->GetType() > CBotTypDouble ) { ex = CBotErrBadNum ; return true; }
// retrieves this number
int n = pVar->GetValInt();
if (n > static_cast<int>(s.length())) n = s.length();
if (n < 0) n = 0;
// no third parameter
if ( pVar->GetNext() != nullptr ) { ex = CBotErrOverParam ; return true; }
// takes the interesting part
s = s.substr(s.length()-n, std::string::npos);
// puts on the stack
pResult->SetValString( s );
return true;
}
////////////////////////////////////////////////////////////////////////////////
bool rStrMid( CBotVar* pVar, CBotVar* pResult, int& ex, void* pUser )
{
// it takes a parameter
if ( pVar == nullptr ) { ex = CBotErrLowParam ; return true; }
// to be a string
if ( pVar->GetType() != CBotTypString ) { ex = CBotErrBadString ; return true; }
// get the contents of the string
std::string s = pVar->GetValString();
// it takes a second parameter
pVar = pVar->GetNext();
if ( pVar == nullptr ) { ex = CBotErrLowParam ; return true; }
// which must be a number
if ( pVar->GetType() > CBotTypDouble ) { ex = CBotErrBadNum ; return true; }
// retrieves this number
int n = pVar->GetValInt();
if (n > static_cast<int>(s.length())) n = s.length();
if (n < 0) n = 0;
// third parameter optional
if ( pVar->GetNext() != nullptr )
{
pVar = pVar->GetNext();
// which must be a number
if ( pVar->GetType() > CBotTypDouble ) { ex = CBotErrBadNum ; return true; }
// retrieves this number
int l = pVar->GetValInt();
if (l > static_cast<int>(s.length())) l = s.length();
if (l < 0) l = 0;
// but no fourth parameter
if ( pVar->GetNext() != nullptr ){ ex = CBotErrOverParam ; return true; }
// takes the interesting part
s = s.substr(n, l);
}
else
{
// takes the interesting part
s = s.substr(n);
}
// puts on the stack
pResult->SetValString( s );
return true;
}
////////////////////////////////////////////////////////////////////////////////
bool rStrVal( CBotVar* pVar, CBotVar* pResult, int& ex, void* pUser )
{
// it takes a parameter
if ( pVar == nullptr ) { ex = CBotErrLowParam ; return true; }
// to be a string
if ( pVar->GetType() != CBotTypString ) { ex = CBotErrBadString ; return true; }
// get the contents of the string
std::string s = pVar->GetValString();
// but no second parameter
if ( pVar->GetNext() != nullptr ){ ex = CBotErrOverParam ; return true; }
float val = GetNumFloat(s);
// puts the value on the stack
pResult->SetValFloat( val );
return true;
}
////////////////////////////////////////////////////////////////////////////////
bool rStrFind( CBotVar* pVar, CBotVar* pResult, int& ex, void* pUser )
{
// it takes a parameter
if ( pVar == nullptr ) { ex = CBotErrLowParam ; return true; }
// to be a string
if ( pVar->GetType() != CBotTypString ) { ex = CBotErrBadString ; return true; }
// get the contents of the string
std::string s = pVar->GetValString();
// it takes a second parameter
pVar = pVar->GetNext();
if ( pVar == nullptr ) { ex = CBotErrLowParam ; return true; }
// to be a string
if ( pVar->GetType() != CBotTypString ) { ex = CBotErrBadString ; return true; }
// retrieves this number
std::string s2 = pVar->GetValString();
// no third parameter
if ( pVar->GetNext() != nullptr ) { ex = CBotErrOverParam ; return true; }
// puts the result on the stack
std::size_t res = s.find(s2);
if (res != std::string::npos)
{
pResult->SetValInt(res);
}
else
{
pResult->SetInit(CBotVar::InitType::IS_NAN);
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
bool rStrUpper( CBotVar* pVar, CBotVar* pResult, int& ex, void* pUser )
{
// it takes a parameter
if ( pVar == nullptr ) { ex = CBotErrLowParam ; return true; }
// to be a string
if ( pVar->GetType() != CBotTypString ) { ex = CBotErrBadString ; return true; }
// get the contents of the string
std::string s = pVar->GetValString();
// but no second parameter
if ( pVar->GetNext() != nullptr ){ ex = CBotErrOverParam ; return true; }
boost::to_upper(s);
// puts the value on the stack
pResult->SetValString( s );
return true;
}
////////////////////////////////////////////////////////////////////////////////
bool rStrLower( CBotVar* pVar, CBotVar* pResult, int& ex, void* pUser )
{
// it takes a parameter
if ( pVar == nullptr ) { ex = CBotErrLowParam ; return true; }
// to be a string
if ( pVar->GetType() != CBotTypString ) { ex = CBotErrBadString ; return true; }
// get the contents of the string
std::string s = pVar->GetValString();
// but no second parameter
if ( pVar->GetNext() != nullptr ){ ex = CBotErrOverParam ; return true; }
boost::to_lower(s);
// puts the value on the stack
pResult->SetValString( s );
return true;
}
} // namespace
////////////////////////////////////////////////////////////////////////////////
void InitStringFunctions()
{
CBotProgram::AddFunction("strlen", rStrLen, cIntStr );
CBotProgram::AddFunction("strleft", rStrLeft, cStrStrInt );
CBotProgram::AddFunction("strright", rStrRight, cStrStrInt );
CBotProgram::AddFunction("strmid", rStrMid, cStrStrIntInt );
CBotProgram::AddFunction("strval", rStrVal, cFloatStr );
CBotProgram::AddFunction("strfind", rStrFind, cIntStrStr );
CBotProgram::AddFunction("strupper", rStrUpper, cStrStr );
CBotProgram::AddFunction("strlower", rStrLower, cStrStr );
}
} // namespace CBot