2016-01-28 14:52:40 +01:00
|
|
|
/** @file
|
|
|
|
|
*
|
|
|
|
|
* @par History
|
|
|
|
|
* - 2006/10/07 Shinigami: GCC 3.4.x fix - added "template<>" to TmplExecutorModule
|
|
|
|
|
* - 2008/07/08 Turley: Added mf_RandomIntMinMax - Return Random Value between...
|
|
|
|
|
* - 2011/01/07 Nando: fix uninit in mf_StrFormatTime - strftime's return is now tested
|
|
|
|
|
*/
|
2016-02-11 22:54:43 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "utilmod.h"
|
2020-11-06 21:57:50 +01:00
|
|
|
#include <algorithm>
|
2018-01-29 21:55:48 +01:00
|
|
|
#include <ctime>
|
|
|
|
|
#include <string>
|
2020-11-06 21:57:50 +01:00
|
|
|
#include <vector>
|
2016-02-11 22:54:43 +01:00
|
|
|
|
|
|
|
|
#include "../../bscript/berror.h"
|
|
|
|
|
#include "../../bscript/impstr.h"
|
|
|
|
|
#include "../../clib/clib.h"
|
|
|
|
|
#include "../../clib/random.h"
|
2018-01-29 21:55:48 +01:00
|
|
|
#include "../dice.h"
|
2016-02-11 22:54:43 +01:00
|
|
|
|
2019-11-10 22:04:08 +01:00
|
|
|
#include <module_defs/util.h>
|
|
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
namespace Pol
|
|
|
|
|
{
|
|
|
|
|
namespace Module
|
|
|
|
|
{
|
|
|
|
|
using namespace Bscript;
|
|
|
|
|
|
2016-12-14 21:50:23 +01:00
|
|
|
UtilExecutorModule::UtilExecutorModule( Bscript::Executor& exec )
|
2020-02-08 09:21:35 +01:00
|
|
|
: Bscript::TmplExecutorModule<UtilExecutorModule, Bscript::ExecutorModule>( exec )
|
2016-12-14 21:50:23 +01:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-19 19:26:35 +01:00
|
|
|
Bscript::BObjectImp* UtilExecutorModule::mf_RandomInt()
|
|
|
|
|
{
|
|
|
|
|
int value;
|
|
|
|
|
if ( exec.getParam( 0, value, 1, INT_MAX ) )
|
|
|
|
|
{
|
|
|
|
|
if ( value > 0 )
|
|
|
|
|
return new BLong( Clib::random_int( value - 1 ) );
|
|
|
|
|
else
|
|
|
|
|
return new BError( "RandomInt() expects a positive integer" );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return new BError( "RandomInt() expects a positive integer" );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Bscript::BObjectImp* UtilExecutorModule::mf_RandomIntMinMax()
|
|
|
|
|
{
|
|
|
|
|
int minvalue;
|
|
|
|
|
if ( exec.getParam( 0, minvalue, INT_MIN, INT_MAX ) )
|
|
|
|
|
{
|
|
|
|
|
int maxvalue;
|
|
|
|
|
if ( exec.getParam( 1, maxvalue, INT_MIN, INT_MAX ) )
|
|
|
|
|
{
|
|
|
|
|
maxvalue--;
|
|
|
|
|
return new BLong( Clib::random_int_range( minvalue, maxvalue ) );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
return new BError( "RandomIntMinMax() expects an integer" );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
return new BError( "RandomIntMinMax() expects an integer" );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Bscript::BObjectImp* UtilExecutorModule::mf_RandomFloat()
|
|
|
|
|
{
|
|
|
|
|
double value;
|
|
|
|
|
if ( exec.getRealParam( 0, value ) )
|
|
|
|
|
{
|
|
|
|
|
return new Double( Clib::random_double( value ) );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return new BError( "RandomFloat() expects a Real parameter" );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Bscript::BObjectImp* UtilExecutorModule::mf_RandomDiceRoll()
|
|
|
|
|
{
|
|
|
|
|
const String* dicestr;
|
|
|
|
|
if ( exec.getStringParam( 0, dicestr ) )
|
|
|
|
|
{
|
|
|
|
|
std::string errormsg;
|
|
|
|
|
Core::Dice dice;
|
|
|
|
|
if ( dice.load( dicestr->data(), &errormsg ) )
|
|
|
|
|
{
|
|
|
|
|
return new BLong( dice.roll() );
|
|
|
|
|
}
|
|
|
|
|
else
|
2016-02-11 22:54:43 +01:00
|
|
|
{
|
2016-02-19 19:26:35 +01:00
|
|
|
return new BError( errormsg.c_str() );
|
|
|
|
|
}
|
2016-02-11 22:54:43 +01:00
|
|
|
}
|
2016-02-19 19:26:35 +01:00
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return new BError( "RandomDiceRoll() expects a String as parameter" );
|
2016-02-11 22:54:43 +01:00
|
|
|
}
|
|
|
|
|
}
|
2016-02-19 19:26:35 +01:00
|
|
|
|
|
|
|
|
Bscript::BObjectImp* UtilExecutorModule::mf_StrFormatTime()
|
|
|
|
|
{
|
|
|
|
|
const String* format_string;
|
|
|
|
|
if ( !getStringParam( 0, format_string ) )
|
|
|
|
|
return new BError( "No time string passed." );
|
|
|
|
|
|
|
|
|
|
int time_stamp;
|
|
|
|
|
if ( !getParam( 1, time_stamp, 0, INT_MAX ) )
|
|
|
|
|
time_stamp = 0;
|
|
|
|
|
|
|
|
|
|
time_t seconds;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( time_stamp <= 0 )
|
2018-07-31 14:30:29 +02:00
|
|
|
seconds = time( nullptr );
|
2016-02-19 19:26:35 +01:00
|
|
|
else
|
|
|
|
|
seconds = time_stamp;
|
|
|
|
|
|
|
|
|
|
auto time_struct = Clib::localtime( seconds );
|
|
|
|
|
|
|
|
|
|
// strftime uses assert check for invalid format -> precheck it
|
|
|
|
|
size_t len = format_string->length();
|
|
|
|
|
const char* str = format_string->data();
|
|
|
|
|
while ( len-- > 0 )
|
|
|
|
|
{
|
|
|
|
|
if ( *str++ == '%' )
|
|
|
|
|
{
|
|
|
|
|
if ( len-- <= 0 )
|
|
|
|
|
return new BError( "Invalid Format string." );
|
|
|
|
|
switch ( *str++ )
|
|
|
|
|
{
|
2020-11-06 21:57:50 +01:00
|
|
|
// vs2019 does not support 0 and E formats
|
|
|
|
|
/*
|
|
|
|
|
case ( '0' ):
|
|
|
|
|
{
|
|
|
|
|
if ( len-- <= 0 )
|
|
|
|
|
return new BError( "Invalid Format string." );
|
|
|
|
|
switch ( *str++ )
|
|
|
|
|
{
|
|
|
|
|
case ( 'd' ):
|
|
|
|
|
case ( 'e' ):
|
|
|
|
|
case ( 'H' ):
|
|
|
|
|
case ( 'I' ):
|
|
|
|
|
case ( 'm' ):
|
|
|
|
|
case ( 'M' ):
|
|
|
|
|
case ( 'S' ):
|
|
|
|
|
case ( 'u' ):
|
|
|
|
|
case ( 'U' ):
|
|
|
|
|
case ( 'V' ):
|
|
|
|
|
case ( 'w' ):
|
|
|
|
|
case ( 'W' ):
|
|
|
|
|
case ( 'y' ):
|
|
|
|
|
continue;
|
|
|
|
|
default:
|
|
|
|
|
return new BError( "Invalid Format string." );
|
|
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
case ( 'E' ):
|
|
|
|
|
{
|
|
|
|
|
if ( len-- <= 0 )
|
|
|
|
|
return new BError( "Invalid Format string." );
|
|
|
|
|
switch ( *str++ )
|
|
|
|
|
{
|
|
|
|
|
case ( 'c' ):
|
|
|
|
|
case ( 'C' ):
|
|
|
|
|
case ( 'x' ):
|
|
|
|
|
case ( 'X' ):
|
|
|
|
|
case ( 'y' ):
|
|
|
|
|
case ( 'Y' ):
|
|
|
|
|
continue;
|
|
|
|
|
default:
|
|
|
|
|
return new BError( "Invalid Format string." );
|
|
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
*/
|
2016-02-19 19:26:35 +01:00
|
|
|
case ( '%' ):
|
|
|
|
|
case ( 'a' ):
|
|
|
|
|
case ( 'A' ):
|
|
|
|
|
case ( 'b' ):
|
|
|
|
|
case ( 'B' ):
|
|
|
|
|
case ( 'c' ):
|
2020-11-06 21:57:50 +01:00
|
|
|
case ( 'C' ):
|
2016-02-19 19:26:35 +01:00
|
|
|
case ( 'd' ):
|
2020-11-06 21:57:50 +01:00
|
|
|
case ( 'D' ):
|
|
|
|
|
case ( 'e' ):
|
|
|
|
|
case ( 'F' ):
|
|
|
|
|
case ( 'g' ):
|
|
|
|
|
case ( 'G' ):
|
|
|
|
|
case ( 'h' ):
|
2016-02-19 19:26:35 +01:00
|
|
|
case ( 'H' ):
|
|
|
|
|
case ( 'I' ):
|
|
|
|
|
case ( 'j' ):
|
2020-11-06 21:57:50 +01:00
|
|
|
case ( 'n' ):
|
2016-02-19 19:26:35 +01:00
|
|
|
case ( 'm' ):
|
|
|
|
|
case ( 'M' ):
|
|
|
|
|
case ( 'p' ):
|
2020-11-06 21:57:50 +01:00
|
|
|
case ( 'r' ):
|
|
|
|
|
case ( 'R' ):
|
2016-02-19 19:26:35 +01:00
|
|
|
case ( 'S' ):
|
2020-11-06 21:57:50 +01:00
|
|
|
case ( 't' ):
|
|
|
|
|
case ( 'T' ):
|
|
|
|
|
case ( 'u' ):
|
2016-02-19 19:26:35 +01:00
|
|
|
case ( 'U' ):
|
2020-11-06 21:57:50 +01:00
|
|
|
case ( 'V' ):
|
2016-02-19 19:26:35 +01:00
|
|
|
case ( 'w' ):
|
|
|
|
|
case ( 'W' ):
|
|
|
|
|
case ( 'x' ):
|
|
|
|
|
case ( 'X' ):
|
|
|
|
|
case ( 'y' ):
|
|
|
|
|
case ( 'Y' ):
|
2020-11-06 21:57:50 +01:00
|
|
|
case ( 'z' ):
|
2016-02-19 19:26:35 +01:00
|
|
|
case ( 'Z' ):
|
|
|
|
|
continue;
|
|
|
|
|
case ( '\0' ):
|
|
|
|
|
len = 0;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
return new BError( "Invalid Format string." );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-06 21:57:50 +01:00
|
|
|
std::vector<char> buffer;
|
|
|
|
|
buffer.resize( std::max( format_string->length() * 2, (size_t)50u ) );
|
|
|
|
|
while ( strftime( buffer.data(), buffer.capacity(), format_string->data(), &time_struct ) == 0 )
|
|
|
|
|
{
|
|
|
|
|
buffer.resize( buffer.capacity() * 2 );
|
|
|
|
|
}
|
|
|
|
|
return new String( buffer.data() );
|
2016-02-19 19:26:35 +01:00
|
|
|
}
|
2019-02-01 23:18:43 +01:00
|
|
|
} // namespace Module
|
|
|
|
|
} // namespace Pol
|