mirror of
https://github.com/polserver/polserver
synced 2026-08-13 08:23:08 -04:00
574 lines
15 KiB
C++
574 lines
15 KiB
C++
/*
|
|
History
|
|
=======
|
|
2005/11/24 Shinigami: added itoa for Linux because it is not ANSI C/C++
|
|
2005/11/29 Shinigami: mf_SplitWords will now accept each type of to-split-value as same as in the past
|
|
2006/10/07 Shinigami: FreeBSD fix - changed __linux__ to __unix__
|
|
2006/12/29 Shinigami: mf_SplitWords will not hang server on queue of delimiter
|
|
|
|
Notes
|
|
=======
|
|
|
|
*/
|
|
|
|
#include "../../clib/stl_inc.h"
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
|
|
#include "../../clib/clib.h"
|
|
#include "../../clib/rawtypes.h"
|
|
#include "../../clib/stlutil.h"
|
|
#include "../../clib/strutil.h"
|
|
|
|
#include "../../bscript/berror.h"
|
|
#include "../../bscript/bobject.h"
|
|
#include "../../bscript/execmodl.h"
|
|
#include "../../bscript/executor.h"
|
|
#include "../../bscript/impstr.h"
|
|
|
|
#include "basicmod.h"
|
|
|
|
BObjectImp* BasicExecutorModule::len()
|
|
{
|
|
BObjectImp* imp = exec.getParamImp( 0 );
|
|
if (imp->isa( BObjectImp::OTArray ))
|
|
{
|
|
ObjArray* arr = static_cast<ObjArray*>(imp);
|
|
return new BLong( static_cast<int>(arr->ref_arr.size()) );
|
|
}
|
|
else if (imp->isa(BObjectImp::OTString))
|
|
{
|
|
return new BLong( static_cast<int>(imp->getStringRep().length()) );
|
|
}
|
|
else if (imp->isa( BObjectImp::OTError ))
|
|
{
|
|
BError* err = static_cast<BError*>(imp);
|
|
return new BLong( static_cast<int>(err->mapcount()) );
|
|
}
|
|
else
|
|
{
|
|
return new BLong(0);
|
|
}
|
|
}
|
|
|
|
BObjectImp* BasicExecutorModule::find()
|
|
{
|
|
exec.makeString(0);
|
|
String* str = static_cast<String*>(exec.getParamImp(0));
|
|
const char *s = exec.paramAsString(1);
|
|
int d = static_cast<int>(exec.paramAsLong(2));
|
|
|
|
int posn = str->find(d ? (d - 1) : 0, s) + 1;
|
|
|
|
return new BLong (posn);
|
|
}
|
|
|
|
BObjectImp* BasicExecutorModule::mf_substr()
|
|
{
|
|
exec.makeString(0);
|
|
String* str = static_cast<String*>(exec.getParamImp(0));
|
|
int start = static_cast<int>(exec.paramAsLong(1));
|
|
int length = static_cast<int>(exec.paramAsLong(2));
|
|
|
|
return str->StrStr(start, length);
|
|
}
|
|
|
|
BObjectImp* BasicExecutorModule::mf_Trim()
|
|
{
|
|
BObjectImp* imp = exec.getParamImp( 0 );
|
|
if ( !(imp->isa(BObjectImp::OTString)) )
|
|
{
|
|
return new BError("Param 1 must be a string.");
|
|
}
|
|
String *string = static_cast<String*>(imp);
|
|
int type = static_cast<int>(exec.paramAsLong(1));
|
|
const char* cset = exec.paramAsString(2);
|
|
if ( type > 3 )
|
|
type = 3;
|
|
if ( type < 1 )
|
|
type = 1;
|
|
|
|
return string->ETrim(cset, type);
|
|
}
|
|
|
|
/*
|
|
eScript Function Useage
|
|
|
|
StrReplace(str, to_replace, replace_with);
|
|
*/
|
|
BObjectImp* BasicExecutorModule::mf_StrReplace()
|
|
{
|
|
BObjectImp* imp = exec.getParamImp( 0 );
|
|
auto_ptr<String> string( new String(imp->getStringRep().c_str()) );
|
|
String *to_replace = static_cast<String*>(exec.getParamImp(1,BObjectImp::OTString));
|
|
if (!to_replace)
|
|
return new BError( "Invalid parameter type" );
|
|
String *replace_with = static_cast<String*>(exec.getParamImp(2,BObjectImp::OTString));
|
|
if (!replace_with)
|
|
return new BError( "Invalid parameter type" );
|
|
|
|
if (string->length() < 1)
|
|
return new BError("Cannot use empty string for string haystack.");
|
|
if (to_replace->length() < 1)
|
|
return new BError("Cannot use empty string for string needle.");
|
|
|
|
string->EStrReplace(to_replace, replace_with);
|
|
|
|
return string.release();
|
|
}
|
|
|
|
// SubStrReplace(str, replace_with, start, length:=0);
|
|
BObjectImp* BasicExecutorModule::mf_SubStrReplace()
|
|
{
|
|
BObjectImp* imp = exec.getParamImp( 0 );
|
|
auto_ptr<String> string( new String(imp->getStringRep().c_str()) );
|
|
String *replace_with = static_cast<String*>(exec.getParamImp(1,BObjectImp::OTString));
|
|
if (!replace_with)
|
|
return new BError( "Invalid parameter type" );
|
|
int index = static_cast<int>(exec.paramAsLong(2));
|
|
int len = static_cast<int>(exec.paramAsLong(3));
|
|
|
|
if ( index < 0 )
|
|
return new BError("Index must not be negative");
|
|
if ( static_cast<unsigned>(index-1) > string->length() )
|
|
return new BError("Index out of range");
|
|
|
|
// We set it to 1 because of doing -1 later to stay with eScript handling.
|
|
if ( !index )
|
|
index = 1;
|
|
|
|
if ( static_cast<unsigned>(len) > (string->length()-index) )
|
|
return new BError("Length out of range");
|
|
if ( len < 0 )
|
|
return new BError("Length must not be negative");
|
|
|
|
if ( !len )
|
|
len = static_cast<int>(replace_with->length() - index);
|
|
|
|
string->ESubStrReplace(replace_with, static_cast<unsigned>(index), static_cast<unsigned>(len));
|
|
|
|
return string.release();
|
|
}
|
|
|
|
// OMG I HATED THIS REQUEST. Ugly code, but necessary for all the checks
|
|
// just in case someone's code is bugged :(
|
|
BObjectImp* BasicExecutorModule::mf_Compare()
|
|
{
|
|
string str1 = exec.paramAsString(0);
|
|
string str2 = exec.paramAsString(1);
|
|
int pos1_index = static_cast<int>(exec.paramAsLong(2));
|
|
int pos1_len = static_cast<int>(exec.paramAsLong(3));
|
|
int pos2_index = static_cast<int>(exec.paramAsLong(4));
|
|
int pos2_len = static_cast<int>(exec.paramAsLong(5));
|
|
|
|
if ( pos1_index != 0 )
|
|
{
|
|
if ( pos1_index < 0 )
|
|
return new BError("Index must not be negative for param 1");
|
|
if ( static_cast<unsigned>(pos1_index-1) > str1.length() )
|
|
return new BError("Index out of range for param 1");
|
|
}
|
|
if ( pos2_index != 0 )
|
|
{
|
|
if ( pos2_index < 0 )
|
|
return new BError("Index must not be negative for param 2");
|
|
if ( static_cast<unsigned>(pos2_index-1) > str2.length() )
|
|
return new BError("Index out of range for param 2");
|
|
}
|
|
|
|
|
|
if ( pos1_len < 0 )
|
|
return new BError("Length must not be negative for param 1");
|
|
if ( static_cast<unsigned>(pos1_len) > (str1.length()-pos1_index) )
|
|
return new BError("Length out of range for param 1");
|
|
if ( pos2_len < 0 )
|
|
return new BError("Length must not be negative for param 2");
|
|
if ( static_cast<unsigned>(pos2_len) > (str2.length()-pos2_index) )
|
|
return new BError("Length out of range for param 2");
|
|
|
|
|
|
if ( pos1_index == 0 )
|
|
{
|
|
unsigned int result = str1.compare(str2);
|
|
if ( result != 0 )
|
|
return new BLong(0);
|
|
else
|
|
return new BLong(1);
|
|
}
|
|
else if ( pos1_index > 0 && pos2_index == 0 )
|
|
{
|
|
unsigned int result = str1.compare(pos1_index-1, pos1_len, str2);
|
|
if ( result != 0 )
|
|
return new BLong(0);
|
|
else
|
|
return new BLong(1);
|
|
}
|
|
else
|
|
{
|
|
unsigned int result = str1.compare(pos1_index-1, pos1_len, str2, pos2_index-1, pos2_len);
|
|
if ( result != 0 )
|
|
return new BLong(0);
|
|
else
|
|
return new BLong(1);
|
|
}
|
|
}
|
|
|
|
BObjectImp* BasicExecutorModule::lower()
|
|
{
|
|
String *string = new String( exec.paramAsString(0) );
|
|
string->toLower();
|
|
return string;
|
|
}
|
|
|
|
BObjectImp* BasicExecutorModule::upper()
|
|
{
|
|
String *string = new String( exec.paramAsString(0) );
|
|
string->toUpper();
|
|
return string;
|
|
}
|
|
|
|
BObjectImp* BasicExecutorModule::mf_CInt()
|
|
{
|
|
BObjectImp* imp = exec.getParamImp( 0 );
|
|
if (imp->isa( BObjectImp::OTLong ))
|
|
{
|
|
return imp->copy();
|
|
}
|
|
else if (imp->isa( BObjectImp::OTString ))
|
|
{
|
|
String* str = static_cast<String*>(imp);
|
|
return new BLong( strtoul( str->data(), NULL, 0 ) );
|
|
}
|
|
else if (imp->isa( BObjectImp::OTDouble ))
|
|
{
|
|
Double* dbl = static_cast<Double*>(imp);
|
|
return new BLong( static_cast<int>(dbl->value()) );
|
|
}
|
|
else
|
|
{
|
|
return new BLong(0);
|
|
}
|
|
}
|
|
|
|
BObjectImp* BasicExecutorModule::mf_CDbl()
|
|
{
|
|
BObjectImp* imp = exec.getParamImp( 0 );
|
|
if (imp->isa( BObjectImp::OTLong ))
|
|
{
|
|
BLong* lng = static_cast<BLong*>(imp);
|
|
return new Double( lng->value() );
|
|
}
|
|
else if (imp->isa( BObjectImp::OTString ))
|
|
{
|
|
String* str = static_cast<String*>(imp);
|
|
return new Double( strtod( str->data(), NULL ) );
|
|
}
|
|
else if (imp->isa( BObjectImp::OTDouble ))
|
|
{
|
|
return imp->copy();
|
|
}
|
|
else
|
|
{
|
|
return new Double(0);
|
|
}
|
|
}
|
|
|
|
BObjectImp* BasicExecutorModule::mf_CStr()
|
|
{
|
|
BObjectImp* imp = exec.getParamImp(0);
|
|
return new String( imp->getStringRep() );
|
|
}
|
|
|
|
BObjectImp* BasicExecutorModule::mf_CAsc()
|
|
{
|
|
BObjectImp* imp = exec.getParamImp( 0 );
|
|
if (imp->isa( BObjectImp::OTString ))
|
|
{
|
|
String* str = static_cast<String*>(imp);
|
|
return new BLong( static_cast<unsigned char>(str->data()[0]) );
|
|
}
|
|
else
|
|
{
|
|
return new BError( "Invalid parameter type" );
|
|
}
|
|
}
|
|
|
|
BObjectImp* BasicExecutorModule::mf_CAscZ()
|
|
{
|
|
BObjectImp* imp = exec.getParamImp( 0 );
|
|
string tmp = imp->getStringRep();
|
|
int nullterm = static_cast<int>(exec.paramAsLong(1));
|
|
auto_ptr<ObjArray> arr (new ObjArray);
|
|
for( size_t i = 0; i < tmp.size(); ++i )
|
|
{
|
|
arr->addElement( new BLong( static_cast<unsigned char>(tmp[i]) ) );
|
|
}
|
|
if (nullterm)
|
|
arr->addElement( new BLong( 0 ) );
|
|
|
|
return arr.release();
|
|
}
|
|
|
|
BObjectImp* BasicExecutorModule::mf_CChr()
|
|
{
|
|
int val;
|
|
if (getParam( 0, val ))
|
|
{
|
|
char s[2];
|
|
s[0] = static_cast<char>(val);
|
|
s[1] = '\0';
|
|
return new String( s );
|
|
}
|
|
else
|
|
{
|
|
return new BError( "Invalid parameter type" );
|
|
}
|
|
}
|
|
|
|
BObjectImp* BasicExecutorModule::mf_CChrZ()
|
|
{
|
|
string res;
|
|
ObjArray* arr = static_cast<ObjArray*>(exec.getParamImp( 0, BObjectImp::OTArray ));
|
|
int break_first_null = static_cast<int>(exec.paramAsLong(1));
|
|
if (!arr)
|
|
return new BError( "Invalid parameter type" );
|
|
for( ObjArray::const_iterator itr = arr->ref_arr.begin(), itrend = arr->ref_arr.end(); itr != itrend; ++itr )
|
|
{
|
|
BObject *bo = (itr->get());
|
|
if ( bo == NULL )
|
|
continue;
|
|
BObjectImp* imp = bo->impptr();
|
|
if (imp)
|
|
{
|
|
if (imp->isa( BObjectImp::OTLong ))
|
|
{
|
|
BLong* blong = static_cast<BLong*>(imp);
|
|
if (break_first_null && blong->value() == 0)
|
|
break;
|
|
char s[2];
|
|
s[0] = static_cast<char>(blong->value());
|
|
s[1] = '\0';
|
|
res += s;
|
|
}
|
|
}
|
|
|
|
}
|
|
return new String(res);
|
|
|
|
}
|
|
|
|
BObjectImp* BasicExecutorModule::mf_Hex()
|
|
{
|
|
BObjectImp* imp = exec.getParamImp(0);
|
|
if (imp->isa( BObjectImp::OTLong ))
|
|
{
|
|
BLong* plong = static_cast<BLong*>(imp);
|
|
char s[20];
|
|
sprintf( s, "0x%lX", static_cast<unsigned long>(plong->value()) );
|
|
return new String( s );
|
|
}
|
|
else if (imp->isa( BObjectImp::OTDouble ))
|
|
{
|
|
Double* pdbl = static_cast<Double*>(imp);
|
|
char s[20];
|
|
sprintf( s, "0x%lX", static_cast<unsigned long>(pdbl->value()) );
|
|
return new String( s );
|
|
}
|
|
else if (imp->isa( BObjectImp::OTString ))
|
|
{
|
|
String* str = static_cast<String*>(imp);
|
|
char s[20];
|
|
sprintf( s, "0x%lX", strtoul( str->data(), NULL, 0 ) );
|
|
return new String( s );
|
|
}
|
|
else
|
|
{
|
|
return new BError( "Hex() expects an Integer, Real, or String" );
|
|
}
|
|
}
|
|
|
|
#ifdef __unix__
|
|
char* itoa( int value, char* result, int base ) {
|
|
// check that the base is valid
|
|
if (base < 2 || base > 16) { *result = 0; return result; }
|
|
|
|
char* out = result;
|
|
int quotient = value;
|
|
|
|
do {
|
|
*out = "0123456789abcdef"[ std::abs( quotient % base ) ];
|
|
++out;
|
|
quotient /= base;
|
|
} while ( quotient );
|
|
|
|
// Only apply negative sign for base 10
|
|
if ( value < 0 && base == 10) *out++ = '-';
|
|
|
|
std::reverse( result, out );
|
|
*out = 0;
|
|
return result;
|
|
}
|
|
#endif
|
|
|
|
BObjectImp* BasicExecutorModule::mf_Bin()
|
|
{
|
|
BObjectImp* imp = exec.getParamImp(0);
|
|
if (imp->isa( BObjectImp::OTLong ))
|
|
{
|
|
BLong* plong = static_cast<BLong*>(imp);
|
|
int number = plong->value();
|
|
char buffer [sizeof(int)*8+1];
|
|
return new String(itoa(number, buffer, 2));
|
|
}
|
|
else
|
|
{
|
|
return new BError( "Bin() expects an Integer" );
|
|
}
|
|
}
|
|
|
|
int bpx;
|
|
void bphelp()
|
|
{
|
|
++bpx;
|
|
}
|
|
|
|
BObjectImp* BasicExecutorModule::mf_SplitWords()
|
|
{
|
|
BObjectImp* bimp_split = exec.getParamImp(0);
|
|
string source = bimp_split->getStringRep();
|
|
|
|
const String* bimp_delimiter;
|
|
if ( !exec.getStringParam(1, bimp_delimiter) )
|
|
{
|
|
return new BError("Invalid parameter type.");
|
|
}
|
|
string delimiter = bimp_delimiter->getStringRep();
|
|
|
|
auto_ptr<ObjArray> objarr (new ObjArray);
|
|
|
|
// Support for how it previously worked.
|
|
// Kept to support spaces and tabs as the same.
|
|
if ( delimiter == " " )
|
|
{
|
|
ISTRINGSTREAM is(source);
|
|
string tmp;
|
|
while ( is >> tmp )
|
|
{
|
|
objarr->addElement(new String(tmp));
|
|
tmp = "";
|
|
}
|
|
return objarr.release();
|
|
}
|
|
|
|
// New delimiter support.
|
|
string new_string = source;
|
|
string::size_type found;
|
|
do
|
|
{
|
|
found = new_string.find(delimiter, 0);
|
|
if ( found == string::npos )
|
|
break;
|
|
|
|
string add_string = new_string.substr(0, found);
|
|
|
|
// Shinigami: will not hang server on queue of delimiter
|
|
// if ( add_string.empty() )
|
|
// continue;
|
|
|
|
objarr->addElement(new String(add_string));
|
|
string tmp_string = new_string.substr(found+delimiter.length(), new_string.length());
|
|
new_string = tmp_string;
|
|
}
|
|
while ( found != string::npos/*-1*/ );
|
|
|
|
// Catch leftovers here.
|
|
if ( !new_string.empty() )
|
|
objarr->addElement(new String(new_string));
|
|
|
|
return objarr.release();
|
|
}
|
|
|
|
BObjectImp* BasicExecutorModule::mf_Pack()
|
|
{
|
|
BObjectImp* imp = exec.getParamImp(0);
|
|
return new String( imp->pack() );
|
|
}
|
|
|
|
BObjectImp* BasicExecutorModule::mf_Unpack()
|
|
{
|
|
const String* str;
|
|
|
|
if (exec.getStringParam( 0, str ))
|
|
{
|
|
return BObjectImp::unpack( str->data() );
|
|
}
|
|
else
|
|
{
|
|
return new BError( "Invalid parameter type" );
|
|
}
|
|
}
|
|
BObjectImp* BasicExecutorModule::mf_TypeOf()
|
|
{
|
|
BObjectImp* imp = exec.getParamImp(0);
|
|
return new String( imp->typeOf() );
|
|
}
|
|
BObjectImp* BasicExecutorModule::mf_SizeOf()
|
|
{
|
|
BObjectImp* imp = exec.getParamImp(0);
|
|
return new BLong( static_cast<int>(imp->sizeEstimate()) );
|
|
}
|
|
BObjectImp* BasicExecutorModule::mf_TypeOfInt()
|
|
{
|
|
BObjectImp* imp = exec.getParamImp(0);
|
|
return new BLong( imp->typeOfInt() );
|
|
}
|
|
|
|
BasicFunctionDef BasicExecutorModule::function_table[] =
|
|
{
|
|
{ "find", &BasicExecutorModule::find },
|
|
{ "len", &BasicExecutorModule::len },
|
|
{ "upper", &BasicExecutorModule::upper },
|
|
{ "lower", &BasicExecutorModule::lower },
|
|
{ "Substr", &BasicExecutorModule::mf_substr },
|
|
{ "Trim", &BasicExecutorModule::mf_Trim },
|
|
{ "StrReplace", &BasicExecutorModule::mf_StrReplace },
|
|
{ "SubStrReplace", &BasicExecutorModule::mf_SubStrReplace },
|
|
{ "Compare", &BasicExecutorModule::mf_Compare },
|
|
{ "CInt", &BasicExecutorModule::mf_CInt },
|
|
{ "CStr", &BasicExecutorModule::mf_CStr },
|
|
{ "CDbl", &BasicExecutorModule::mf_CDbl },
|
|
{ "CAsc", &BasicExecutorModule::mf_CAsc },
|
|
{ "CChr", &BasicExecutorModule::mf_CChr },
|
|
{ "CAscZ", &BasicExecutorModule::mf_CAscZ },
|
|
{ "CChrZ", &BasicExecutorModule::mf_CChrZ },
|
|
{ "Bin", &BasicExecutorModule::mf_Bin },
|
|
{ "Hex", &BasicExecutorModule::mf_Hex },
|
|
{ "SplitWords", &BasicExecutorModule::mf_SplitWords },
|
|
{ "Pack", &BasicExecutorModule::mf_Pack },
|
|
{ "Unpack", &BasicExecutorModule::mf_Unpack },
|
|
{ "TypeOf", &BasicExecutorModule::mf_TypeOf },
|
|
{ "SizeOf", &BasicExecutorModule::mf_SizeOf },
|
|
{ "TypeOfInt", &BasicExecutorModule::mf_TypeOfInt }
|
|
};
|
|
|
|
int BasicExecutorModule::functionIndex( const char *name )
|
|
{
|
|
for( unsigned idx = 0; idx < arsize(function_table); idx++ )
|
|
{
|
|
if (stricmp( name, function_table[idx].funcname ) == 0)
|
|
return idx;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
BObjectImp* BasicExecutorModule::execFunc( unsigned funcidx )
|
|
{
|
|
return callMemberFunction(*this, function_table[funcidx].fptr)();
|
|
};
|
|
|
|
std::string BasicExecutorModule::functionName( unsigned idx )
|
|
{
|
|
return function_table[idx].funcname;
|
|
}
|