Initial import

This commit is contained in:
Kevin Bentley
2024-04-15 21:43:29 -06:00
parent 637df31ca1
commit df209742fc
1267 changed files with 1030711 additions and 2 deletions

View File

@@ -0,0 +1,705 @@
#include <assert.h>
#include <string.h> // strstr
#include <stdio.h> // sprintf
#include "scriptstring.h"
using namespace std;
BEGIN_AS_NAMESPACE
//--------------
// constructors
//--------------
CScriptString::CScriptString()
{
// Count the first reference
refCount = 1;
}
CScriptString::CScriptString(const char *s, unsigned int len)
{
refCount = 1;
buffer.assign(s, len);
}
CScriptString::CScriptString(const string &s)
{
refCount = 1;
buffer = s;
}
CScriptString::CScriptString(const CScriptString &s)
{
refCount = 1;
buffer = s.buffer;
}
CScriptString::~CScriptString()
{
assert( refCount == 0 );
}
//--------------------
// reference counting
//--------------------
void CScriptString::AddRef()
{
refCount++;
}
static void StringAddRef_Generic(asIScriptGeneric *gen)
{
CScriptString *thisPointer = (CScriptString*)gen->GetObject();
thisPointer->AddRef();
}
void CScriptString::Release()
{
if( --refCount == 0 )
delete this;
}
static void StringRelease_Generic(asIScriptGeneric *gen)
{
CScriptString *thisPointer = (CScriptString*)gen->GetObject();
thisPointer->Release();
}
//-----------------
// string = string
//-----------------
CScriptString &CScriptString::operator=(const CScriptString &other)
{
// Copy only the buffer, not the reference counter
buffer = other.buffer;
// Return a reference to this object
return *this;
}
static void AssignString_Generic(asIScriptGeneric *gen)
{
CScriptString *a = (CScriptString*)gen->GetArgAddress(0);
CScriptString *thisPointer = (CScriptString*)gen->GetObject();
*thisPointer = *a;
gen->SetReturnAddress(thisPointer);
}
//------------------
// string += string
//------------------
CScriptString &CScriptString::operator+=(const CScriptString &other)
{
buffer += other.buffer;
return *this;
}
static void AddAssignString_Generic(asIScriptGeneric *gen)
{
CScriptString *a = (CScriptString*)gen->GetArgAddress(0);
CScriptString *thisPointer = (CScriptString*)gen->GetObject();
*thisPointer += *a;
gen->SetReturnAddress(thisPointer);
}
//-----------------
// string opCmp string
//-----------------
static int StringCmp(const string &a, const string &b)
{
int cmp = 0;
if( a < b ) cmp = -1;
else if( a > b ) cmp = 1;
return cmp;
}
static void StringCmp_Generic(asIScriptGeneric * gen)
{
string * a = static_cast<string *>(gen->GetObject());
string * b = static_cast<string *>(gen->GetArgAddress(0));
int cmp = 0;
if( *a < *b ) cmp = -1;
else if( *a > *b ) cmp = 1;
*(int*)gen->GetAddressOfReturnLocation() = cmp;
}
//-----------------
// string + string
//-----------------
CScriptString *operator+(const CScriptString &a, const CScriptString &b)
{
// Return a new object as a script handle
CScriptString *str = new CScriptString();
// Avoid unnecessary memory copying by first reserving the full memory buffer, then concatenating
str->buffer.reserve(a.buffer.length() + b.buffer.length());
str->buffer += a.buffer;
str->buffer += b.buffer;
return str;
}
static void ConcatenateStrings_Generic(asIScriptGeneric *gen)
{
CScriptString *a = (CScriptString*)gen->GetObject();
CScriptString *b = (CScriptString*)gen->GetArgAddress(0);
CScriptString *out = *a + *b;
gen->SetReturnAddress(out);
}
//----------------
// string = value
//----------------
static CScriptString &AssignUIntToString(unsigned int i, CScriptString &dest)
{
char buf[100];
sprintf(buf, "%u", i);
dest.buffer = buf;
return dest;
}
static void AssignUIntToString_Generic(asIScriptGeneric *gen)
{
unsigned int i = gen->GetArgDWord(0);
CScriptString *thisPointer = (CScriptString*)gen->GetObject();
AssignUIntToString(i, *thisPointer);
gen->SetReturnAddress(thisPointer);
}
static CScriptString &AssignIntToString(int i, CScriptString &dest)
{
char buf[100];
sprintf(buf, "%d", i);
dest.buffer = buf;
return dest;
}
static void AssignIntToString_Generic(asIScriptGeneric *gen)
{
int i = gen->GetArgDWord(0);
CScriptString *thisPointer = (CScriptString*)gen->GetObject();
AssignIntToString(i, *thisPointer);
gen->SetReturnAddress(thisPointer);
}
static CScriptString &AssignFloatToString(float f, CScriptString &dest)
{
char buf[100];
sprintf(buf, "%g", f);
dest.buffer = buf;
return dest;
}
static void AssignFloatToString_Generic(asIScriptGeneric *gen)
{
float f = gen->GetArgFloat(0);
CScriptString *thisPointer = (CScriptString*)gen->GetObject();
AssignFloatToString(f, *thisPointer);
gen->SetReturnAddress(thisPointer);
}
static CScriptString &AssignDoubleToString(double f, CScriptString &dest)
{
char buf[100];
sprintf(buf, "%g", f);
dest.buffer = buf;
return dest;
}
static void AssignDoubleToString_Generic(asIScriptGeneric *gen)
{
double f = gen->GetArgDouble(0);
CScriptString *thisPointer = (CScriptString*)gen->GetObject();
AssignDoubleToString(f, *thisPointer);
gen->SetReturnAddress(thisPointer);
}
//-----------------
// string += value
//-----------------
static CScriptString &AddAssignUIntToString(unsigned int i, CScriptString &dest)
{
char buf[100];
sprintf(buf, "%u", i);
dest.buffer += buf;
return dest;
}
static void AddAssignUIntToString_Generic(asIScriptGeneric *gen)
{
unsigned int i = gen->GetArgDWord(0);
CScriptString *thisPointer = (CScriptString*)gen->GetObject();
AddAssignUIntToString(i, *thisPointer);
gen->SetReturnAddress(thisPointer);
}
static CScriptString &AddAssignIntToString(int i, CScriptString &dest)
{
char buf[100];
sprintf(buf, "%d", i);
dest.buffer += buf;
return dest;
}
static void AddAssignIntToString_Generic(asIScriptGeneric *gen)
{
int i = gen->GetArgDWord(0);
CScriptString *thisPointer = (CScriptString*)gen->GetObject();
AddAssignIntToString(i, *thisPointer);
gen->SetReturnAddress(thisPointer);
}
static CScriptString &AddAssignFloatToString(float f, CScriptString &dest)
{
char buf[100];
sprintf(buf, "%g", f);
dest.buffer += buf;
return dest;
}
static void AddAssignFloatToString_Generic(asIScriptGeneric *gen)
{
float f = gen->GetArgFloat(0);
CScriptString *thisPointer = (CScriptString*)gen->GetObject();
AddAssignFloatToString(f, *thisPointer);
gen->SetReturnAddress(thisPointer);
}
static CScriptString &AddAssignDoubleToString(double f, CScriptString &dest)
{
char buf[100];
sprintf(buf, "%g", f);
dest.buffer += buf;
return dest;
}
static void AddAssignDoubleToString_Generic(asIScriptGeneric *gen)
{
double f = gen->GetArgDouble(0);
CScriptString *thisPointer = (CScriptString*)gen->GetObject();
AddAssignDoubleToString(f, *thisPointer);
gen->SetReturnAddress(thisPointer);
}
//----------------
// string + value
//----------------
static CScriptString *AddStringUInt(const CScriptString &str, unsigned int i)
{
char buf[100];
sprintf(buf, "%u", i);
return new CScriptString(str.buffer + buf);
}
static void AddStringUInt_Generic(asIScriptGeneric *gen)
{
CScriptString *str = (CScriptString*)gen->GetObject();
unsigned int i = gen->GetArgDWord(0);
CScriptString *out = AddStringUInt(*str, i);
gen->SetReturnAddress(out);
}
static CScriptString *AddStringInt(const CScriptString &str, int i)
{
char buf[100];
sprintf(buf, "%d", i);
return new CScriptString(str.buffer + buf);
}
static void AddStringInt_Generic(asIScriptGeneric *gen)
{
CScriptString *str = (CScriptString*)gen->GetObject();
int i = gen->GetArgDWord(0);
CScriptString *out = AddStringInt(*str, i);
gen->SetReturnAddress(out);
}
static CScriptString *AddStringFloat(const CScriptString &str, float f)
{
char buf[100];
sprintf(buf, "%g", f);
return new CScriptString(str.buffer + buf);
}
static void AddStringFloat_Generic(asIScriptGeneric *gen)
{
CScriptString *str = (CScriptString*)gen->GetObject();
float f = gen->GetArgFloat(0);
CScriptString *out = AddStringFloat(*str, f);
gen->SetReturnAddress(out);
}
static CScriptString *AddStringDouble(const CScriptString &str, double f)
{
char buf[100];
sprintf(buf, "%g", f);
return new CScriptString(str.buffer + buf);
}
static void AddStringDouble_Generic(asIScriptGeneric *gen)
{
CScriptString *str = (CScriptString*)gen->GetObject();
double f = gen->GetArgDouble(0);
CScriptString *out = AddStringDouble(*str, f);
gen->SetReturnAddress(out);
}
//----------------
// value + string
//----------------
static CScriptString *AddIntString(int i, const CScriptString &str)
{
char buf[100];
sprintf(buf, "%d", i);
return new CScriptString(buf + str.buffer);
}
static void AddIntString_Generic(asIScriptGeneric *gen)
{
int i = gen->GetArgDWord(0);
CScriptString *str = (CScriptString*)gen->GetObject();
CScriptString *out = AddIntString(i, *str);
gen->SetReturnAddress(out);
}
static CScriptString *AddUIntString(unsigned int i, const CScriptString &str)
{
char buf[100];
sprintf(buf, "%u", i);
return new CScriptString(buf + str.buffer);
}
static void AddUIntString_Generic(asIScriptGeneric *gen)
{
unsigned int i = gen->GetArgDWord(0);
CScriptString *str = (CScriptString*)gen->GetObject();
CScriptString *out = AddUIntString(i, *str);
gen->SetReturnAddress(out);
}
static CScriptString *AddFloatString(float f, const CScriptString &str)
{
char buf[100];
sprintf(buf, "%g", f);
return new CScriptString(buf + str.buffer);
}
static void AddFloatString_Generic(asIScriptGeneric *gen)
{
float f = gen->GetArgFloat(0);
CScriptString *str = (CScriptString*)gen->GetObject();
CScriptString *out = AddFloatString(f, *str);
gen->SetReturnAddress(out);
}
static CScriptString *AddDoubleString(double f, const CScriptString &str)
{
char buf[100];
sprintf(buf, "%g", f);
return new CScriptString(buf + str.buffer);
}
static void AddDoubleString_Generic(asIScriptGeneric *gen)
{
double f = gen->GetArgDouble(0);
CScriptString *str = (CScriptString*)gen->GetObject();
CScriptString *out = AddDoubleString(f, *str);
gen->SetReturnAddress(out);
}
//----------
// string[]
//----------
static char *StringCharAt(unsigned int i, CScriptString &str)
{
if( i >= str.buffer.size() )
{
// Set a script exception
asIScriptContext *ctx = asGetActiveContext();
ctx->SetException("Out of range");
// Return a null pointer
return 0;
}
return &str.buffer[i];
}
static void StringCharAt_Generic(asIScriptGeneric *gen)
{
unsigned int i = gen->GetArgDWord(0);
CScriptString *str = (CScriptString*)gen->GetObject();
char *ch = StringCharAt(i, *str);
gen->SetReturnAddress(ch);
}
//-----------------------
// AngelScript functions
//-----------------------
// This is the string factory that creates new strings for the script based on string literals
static CScriptString *StringFactory(asUINT length, const char *s)
{
return new CScriptString(s, length);
}
static void StringFactory_Generic(asIScriptGeneric *gen)
{
asUINT length = gen->GetArgDWord(0);
const char *s = (const char*)gen->GetArgAddress(1);
CScriptString *str = StringFactory(length, s);
gen->SetReturnAddress(str);
}
// This is the default string factory, that is responsible for creating empty string objects, e.g. when a variable is declared
static CScriptString *StringDefaultFactory()
{
// Allocate and initialize with the default constructor
return new CScriptString();
}
static CScriptString *StringCopyFactory(const CScriptString &other)
{
// Allocate and initialize with the copy constructor
return new CScriptString(other);
}
static void StringDefaultFactory_Generic(asIScriptGeneric *gen)
{
*(CScriptString**)gen->GetAddressOfReturnLocation() = StringDefaultFactory();
}
static void StringCopyFactory_Generic(asIScriptGeneric *gen)
{
CScriptString *other = (CScriptString *)gen->GetArgObject(0);
*(CScriptString**)gen->GetAddressOfReturnLocation() = StringCopyFactory(*other);
}
static void StringEqual_Generic(asIScriptGeneric *gen)
{
string *a = (string*)gen->GetArgAddress(0);
string *b = (string*)gen->GetArgAddress(1);
bool r = *a == *b;
*(bool*)gen->GetAddressOfReturnLocation() = r;
}
static void StringEquals_Generic(asIScriptGeneric * gen)
{
string * a = static_cast<string *>(gen->GetObject());
string * b = static_cast<string *>(gen->GetArgAddress(0));
*(bool*)gen->GetAddressOfReturnLocation() = (*a == *b);
}
static void StringNotEqual_Generic(asIScriptGeneric *gen)
{
string *a = (string*)gen->GetArgAddress(0);
string *b = (string*)gen->GetArgAddress(1);
bool r = *a != *b;
*(bool*)gen->GetAddressOfReturnLocation() = r;
}
static void StringLesserOrEqual_Generic(asIScriptGeneric *gen)
{
string *a = (string*)gen->GetArgAddress(0);
string *b = (string*)gen->GetArgAddress(1);
bool r = *a <= *b;
*(bool*)gen->GetAddressOfReturnLocation() = r;
}
static void StringGreaterOrEqual_Generic(asIScriptGeneric *gen)
{
string *a = (string*)gen->GetArgAddress(0);
string *b = (string*)gen->GetArgAddress(1);
bool r = *a >= *b;
*(bool*)gen->GetAddressOfReturnLocation() = r;
}
static void StringLesser_Generic(asIScriptGeneric *gen)
{
string *a = (string*)gen->GetArgAddress(0);
string *b = (string*)gen->GetArgAddress(1);
bool r = *a < *b;
*(bool*)gen->GetAddressOfReturnLocation() = r;
}
static void StringGreater_Generic(asIScriptGeneric *gen)
{
string *a = (string*)gen->GetArgAddress(0);
string *b = (string*)gen->GetArgAddress(1);
bool r = *a > *b;
*(bool*)gen->GetAddressOfReturnLocation() = r;
}
static void StringLength_Generic(asIScriptGeneric *gen)
{
string *s = (string*)gen->GetObject();
size_t l = s->size();
if( sizeof(size_t) == 4 )
gen->SetReturnDWord((asUINT)l);
else
gen->SetReturnQWord((asQWORD)l);
}
static void StringResize_Generic(asIScriptGeneric *gen)
{
string *s = (string*)gen->GetObject();
size_t v = *(size_t*)gen->GetAddressOfArg(0);
s->resize(v);
}
// This is where we register the string type
void RegisterScriptString_Native(asIScriptEngine *engine)
{
int r;
// Register the type
r = engine->RegisterObjectType("string", 0, asOBJ_REF); assert( r >= 0 );
// Register the object operator overloads
// Note: We don't have to register the destructor, since the object uses reference counting
r = engine->RegisterObjectBehaviour("string", asBEHAVE_FACTORY, "string @f()", asFUNCTION(StringDefaultFactory), asCALL_CDECL); assert( r >= 0 );
r = engine->RegisterObjectBehaviour("string", asBEHAVE_FACTORY, "string @f(const string &in)", asFUNCTION(StringCopyFactory), asCALL_CDECL); assert( r >= 0 );
r = engine->RegisterObjectBehaviour("string", asBEHAVE_ADDREF, "void f()", asMETHOD(CScriptString,AddRef), asCALL_THISCALL); assert( r >= 0 );
r = engine->RegisterObjectBehaviour("string", asBEHAVE_RELEASE, "void f()", asMETHOD(CScriptString,Release), asCALL_THISCALL); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "string &opAssign(const string &in)", asMETHODPR(CScriptString, operator =, (const CScriptString&), CScriptString&), asCALL_THISCALL); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "string &opAddAssign(const string &in)", asMETHODPR(CScriptString, operator+=, (const CScriptString&), CScriptString&), asCALL_THISCALL); assert( r >= 0 );
// Register the factory to return a handle to a new string
// Note: We must register the string factory after the basic behaviours,
// otherwise the library will not allow the use of object handles for this type
r = engine->RegisterStringFactory("string@", asFUNCTION(StringFactory), asCALL_CDECL); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "bool opEquals(const string &in) const", asFUNCTIONPR(operator ==, (const string &, const string &), bool), asCALL_CDECL_OBJFIRST); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "int opCmp(const string &in) const", asFUNCTION(StringCmp), asCALL_CDECL_OBJFIRST); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "string@ opAdd(const string &in) const", asFUNCTIONPR(operator +, (const CScriptString &, const CScriptString &), CScriptString*), asCALL_CDECL_OBJFIRST); assert( r >= 0 );
// Register the index operator, both as a mutator and as an inspector
r = engine->RegisterObjectBehaviour("string", asBEHAVE_INDEX, "uint8 &f(uint)", asFUNCTION(StringCharAt), asCALL_CDECL_OBJLAST); assert( r >= 0 );
r = engine->RegisterObjectBehaviour("string", asBEHAVE_INDEX, "const uint8 &f(uint) const", asFUNCTION(StringCharAt), asCALL_CDECL_OBJLAST); assert( r >= 0 );
// Register the object methods
if( sizeof(size_t) == 4 )
{
r = engine->RegisterObjectMethod("string", "uint length() const", asMETHOD(string,size), asCALL_THISCALL); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "void resize(uint)", asMETHODPR(string,resize,(size_t),void), asCALL_THISCALL); assert( r >= 0 );
}
else
{
r = engine->RegisterObjectMethod("string", "uint64 length() const", asMETHOD(string,size), asCALL_THISCALL); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "void resize(uint64)", asMETHODPR(string,resize,(size_t),void), asCALL_THISCALL); assert( r >= 0 );
}
// TODO: Add factory string(const string &in str, int repeatCount)
// TODO: Add explicit type conversion via constructor and value cast
// TODO: Add parseInt and parseDouble. Two versions, one without parameter, one with an outparm that returns the number of characters parsed.
// Automatic conversion from values
r = engine->RegisterObjectMethod("string", "string &opAssign(double)", asFUNCTION(AssignDoubleToString), asCALL_CDECL_OBJLAST); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "string &opAddAssign(double)", asFUNCTION(AddAssignDoubleToString), asCALL_CDECL_OBJLAST); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "string@ opAdd(double) const", asFUNCTION(AddStringDouble), asCALL_CDECL_OBJFIRST); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "string@ opAdd_r(double) const", asFUNCTION(AddDoubleString), asCALL_CDECL_OBJLAST); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "string &opAssign(float)", asFUNCTION(AssignFloatToString), asCALL_CDECL_OBJLAST); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "string &opAddAssign(float)", asFUNCTION(AddAssignFloatToString), asCALL_CDECL_OBJLAST); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "string@ opAdd(float) const", asFUNCTION(AddStringFloat), asCALL_CDECL_OBJFIRST); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "string@ opAdd_r(float) const", asFUNCTION(AddFloatString), asCALL_CDECL_OBJLAST); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "string &opAssign(int)", asFUNCTION(AssignIntToString), asCALL_CDECL_OBJLAST); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "string &opAddAssign(int)", asFUNCTION(AddAssignIntToString), asCALL_CDECL_OBJLAST); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "string@ opAdd(int) const", asFUNCTION(AddStringInt), asCALL_CDECL_OBJFIRST); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "string@ opAdd_r(int) const", asFUNCTION(AddIntString), asCALL_CDECL_OBJLAST); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "string &opAssign(uint)", asFUNCTION(AssignUIntToString), asCALL_CDECL_OBJLAST); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "string &opAddAssign(uint)", asFUNCTION(AddAssignUIntToString), asCALL_CDECL_OBJLAST); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "string@ opAdd(uint) const", asFUNCTION(AddStringUInt), asCALL_CDECL_OBJFIRST); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "string@ opAdd_r(uint) const", asFUNCTION(AddUIntString), asCALL_CDECL_OBJLAST); assert( r >= 0 );
}
void RegisterScriptString_Generic(asIScriptEngine *engine)
{
int r;
// Register the type
r = engine->RegisterObjectType("string", 0, asOBJ_REF); assert( r >= 0 );
// Register the object operator overloads
// Note: We don't have to register the destructor, since the object uses reference counting
r = engine->RegisterObjectBehaviour("string", asBEHAVE_FACTORY, "string @f()", asFUNCTION(StringDefaultFactory_Generic), asCALL_GENERIC); assert( r >= 0 );
r = engine->RegisterObjectBehaviour("string", asBEHAVE_FACTORY, "string @f(const string &in)", asFUNCTION(StringCopyFactory_Generic), asCALL_GENERIC); assert( r >= 0 );
r = engine->RegisterObjectBehaviour("string", asBEHAVE_ADDREF, "void f()", asFUNCTION(StringAddRef_Generic), asCALL_GENERIC); assert( r >= 0 );
r = engine->RegisterObjectBehaviour("string", asBEHAVE_RELEASE, "void f()", asFUNCTION(StringRelease_Generic), asCALL_GENERIC); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "string &opAssign(const string &in)", asFUNCTION(AssignString_Generic), asCALL_GENERIC); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "string &opAddAssign(const string &in)", asFUNCTION(AddAssignString_Generic), asCALL_GENERIC); assert( r >= 0 );
// Register the factory to return a handle to a new string
// Note: We must register the string factory after the basic behaviours,
// otherwise the library will not allow the use of object handles for this type
r = engine->RegisterStringFactory("string@", asFUNCTION(StringFactory_Generic), asCALL_GENERIC); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "bool opEquals(const string &in) const", asFUNCTION(StringEquals_Generic), asCALL_GENERIC); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "int opCmp(const string &in) const", asFUNCTION(StringCmp_Generic), asCALL_GENERIC); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "string@ opAdd(const string &in) const", asFUNCTION(ConcatenateStrings_Generic), asCALL_GENERIC); assert( r >= 0 );
// Register the index operator, both as a mutator and as an inspector
r = engine->RegisterObjectBehaviour("string", asBEHAVE_INDEX, "uint8 &f(uint)", asFUNCTION(StringCharAt_Generic), asCALL_GENERIC); assert( r >= 0 );
r = engine->RegisterObjectBehaviour("string", asBEHAVE_INDEX, "const uint8 &f(uint) const", asFUNCTION(StringCharAt_Generic), asCALL_GENERIC); assert( r >= 0 );
// Register the object methods
if( sizeof(size_t) == 4 )
{
r = engine->RegisterObjectMethod("string", "uint length() const", asFUNCTION(StringLength_Generic), asCALL_GENERIC); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "void resize(uint)", asFUNCTION(StringResize_Generic), asCALL_GENERIC); assert( r >= 0 );
}
else
{
r = engine->RegisterObjectMethod("string", "uint64 length() const", asFUNCTION(StringLength_Generic), asCALL_GENERIC); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "void resize(uint64)", asFUNCTION(StringResize_Generic), asCALL_GENERIC); assert( r >= 0 );
}
// Automatic conversion from values
r = engine->RegisterObjectMethod("string", "string &opAssign(double)", asFUNCTION(AssignDoubleToString_Generic), asCALL_GENERIC); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "string &opAddAssign(double)", asFUNCTION(AddAssignDoubleToString_Generic), asCALL_GENERIC); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "string@ opAdd(double) const", asFUNCTION(AddStringDouble_Generic), asCALL_GENERIC); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "string@ opAdd_r(double) const", asFUNCTION(AddDoubleString_Generic), asCALL_GENERIC); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "string &opAssign(float)", asFUNCTION(AssignFloatToString_Generic), asCALL_GENERIC); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "string &opAddAssign(float)", asFUNCTION(AddAssignFloatToString_Generic), asCALL_GENERIC); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "string@ opAdd(float) const", asFUNCTION(AddStringFloat_Generic), asCALL_GENERIC); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "string@ opAdd_r(float) const", asFUNCTION(AddFloatString_Generic), asCALL_GENERIC); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "string &opAssign(int)", asFUNCTION(AssignIntToString_Generic), asCALL_GENERIC); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "string &opAddAssign(int)", asFUNCTION(AddAssignIntToString_Generic), asCALL_GENERIC); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "string@ opAdd(int) const", asFUNCTION(AddStringInt_Generic), asCALL_GENERIC); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "string@ opAdd_r(int) const", asFUNCTION(AddIntString_Generic), asCALL_GENERIC); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "string &opAssign(uint)", asFUNCTION(AssignUIntToString_Generic), asCALL_GENERIC); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "string &opAddAssign(uint)", asFUNCTION(AddAssignUIntToString_Generic), asCALL_GENERIC); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "string@ opAdd(uint) const", asFUNCTION(AddStringUInt_Generic), asCALL_GENERIC); assert( r >= 0 );
r = engine->RegisterObjectMethod("string", "string@ opAdd_r(uint) const", asFUNCTION(AddUIntString_Generic), asCALL_GENERIC); assert( r >= 0 );
}
void RegisterScriptString(asIScriptEngine *engine)
{
if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") )
RegisterScriptString_Generic(engine);
else
RegisterScriptString_Native(engine);
}
END_AS_NAMESPACE

View File

@@ -0,0 +1,64 @@
//
// CScriptString
//
// This class is used to pass strings between the application and the script engine.
// It is basically a container for the normal std::string, with the addition of a
// reference counter so that the script can use object handles to hold the type.
//
// Because the class is reference counted it cannot be stored locally in the
// application functions, nor be received or returned by value. Instead it should
// be manipulated through pointers or references.
//
// Note, because the internal buffer is placed at the beginning of the class
// structure it is infact possible to receive this type as a reference or pointer
// to a normal std::string where the reference counter doesn't have to be manipulated.
//
#ifndef SCRIPTSTRING_H
#define SCRIPTSTRING_H
#include <angelscript.h>
#include <string>
BEGIN_AS_NAMESPACE
class CScriptString
{
public:
CScriptString();
CScriptString(const CScriptString &other);
CScriptString(const char *s, unsigned int len);
CScriptString(const std::string &s);
void AddRef();
void Release();
CScriptString &operator=(const CScriptString &other);
CScriptString &operator+=(const CScriptString &other);
friend CScriptString *operator+(const CScriptString &a, const CScriptString &b);
std::string buffer;
protected:
~CScriptString();
int refCount;
};
// This function will determine the configuration of the engine
// and use one of the two functions below to register the string type
void RegisterScriptString(asIScriptEngine *engine);
// Call this function to register the string type
// using native calling conventions
void RegisterScriptString_Native(asIScriptEngine *engine);
// Use this one instead if native calling conventions
// are not supported on the target platform
void RegisterScriptString_Generic(asIScriptEngine *engine);
// This function will register utility functions for the script string
void RegisterScriptStringUtils(asIScriptEngine *engine);
END_AS_NAMESPACE
#endif

View File

@@ -0,0 +1,369 @@
#include <assert.h>
#include "scriptstring.h"
#include <string.h> // strstr
// This function returns a string containing the substring of the input string
// determined by the starting index and count of characters.
//
// AngelScript signature:
// string@ substring(const string &in str, int start, int count)
void StringSubString_Generic(asIScriptGeneric *gen)
{
// Get the arguments
CScriptString *str = *(CScriptString**)gen->GetAddressOfArg(0);
int start = *(int*)gen->GetAddressOfArg(1);
int count = *(int*)gen->GetAddressOfArg(2);
// Create the substring
CScriptString *sub = new CScriptString();
sub->buffer = str->buffer.substr(start,count);
// Return the substring
*(CScriptString**)gen->GetAddressOfReturnLocation() = sub;
}
// This function returns the index of the first position where the substring
// exists in the input string. If the substring doesn't exist in the input
// string -1 is returned.
//
// AngelScript signature:
// int findFirst(const string &in str, const string &in sub, int start)
void StringFindFirst_Generic(asIScriptGeneric *gen)
{
// Get the arguments
CScriptString *str = *(CScriptString**)gen->GetAddressOfArg(0);
CScriptString *sub = *(CScriptString**)gen->GetAddressOfArg(1);
int start = *(int*)gen->GetAddressOfArg(2);
// Find the substring
int loc = (int)str->buffer.find(sub->buffer, start);
// Return the result
*(int*)gen->GetAddressOfReturnLocation() = loc;
}
// TODO: Angelscript should permit default parameters
void StringFindFirst0_Generic(asIScriptGeneric *gen)
{
// Get the arguments
CScriptString *str = *(CScriptString**)gen->GetAddressOfArg(0);
CScriptString *sub = *(CScriptString**)gen->GetAddressOfArg(1);
// Find the substring
int loc = (int)str->buffer.find(sub->buffer);
// Return the result
*(int*)gen->GetAddressOfReturnLocation() = loc;
}
// This function returns the index of the last position where the substring
// exists in the input string. If the substring doesn't exist in the input
// string -1 is returned.
//
// AngelScript signature:
// int findLast(const string &in str, const string &in sub, int start)
void StringFindLast_Generic(asIScriptGeneric *gen)
{
// Get the arguments
CScriptString *str = *(CScriptString**)gen->GetAddressOfArg(0);
CScriptString *sub = *(CScriptString**)gen->GetAddressOfArg(1);
int start = *(int*)gen->GetAddressOfArg(2);
// Find the substring
int loc = (int)str->buffer.rfind(sub->buffer, start);
// Return the result
*(int*)gen->GetAddressOfReturnLocation() = loc;
}
void StringFindLast0_Generic(asIScriptGeneric *gen)
{
// Get the arguments
CScriptString *str = *(CScriptString**)gen->GetAddressOfArg(0);
CScriptString *sub = *(CScriptString**)gen->GetAddressOfArg(1);
// Find the substring
int loc = (int)str->buffer.rfind(sub->buffer);
// Return the result
*(int*)gen->GetAddressOfReturnLocation() = loc;
}
// This function returns the index of the first character that is in
// the specified set of characters. If no such character is found -1 is
// returned.
//
// AngelScript signature:
// int findFirstOf(const string &in str, const string &in chars, int start)
void StringFindFirstOf_Generic(asIScriptGeneric *gen)
{
// Get the arguments
CScriptString *str = *(CScriptString**)gen->GetAddressOfArg(0);
CScriptString *chars = *(CScriptString**)gen->GetAddressOfArg(1);
int start = *(int*)gen->GetAddressOfArg(2);
// Find the substring
int loc = (int)str->buffer.find_first_of(chars->buffer, start);
// Return the result
*(int*)gen->GetAddressOfReturnLocation() = loc;
}
void StringFindFirstOf0_Generic(asIScriptGeneric *gen)
{
// Get the arguments
CScriptString *str = *(CScriptString**)gen->GetAddressOfArg(0);
CScriptString *chars = *(CScriptString**)gen->GetAddressOfArg(1);
// Find the substring
int loc = (int)str->buffer.find_first_of(chars->buffer);
// Return the result
*(int*)gen->GetAddressOfReturnLocation() = loc;
}
// This function returns the index of the first character that is not in
// the specified set of characters. If no such character is found -1 is
// returned.
//
// AngelScript signature:
// int findFirstNotOf(const string &in str, const string &in chars, int start)
void StringFindFirstNotOf_Generic(asIScriptGeneric *gen)
{
// Get the arguments
CScriptString *str = *(CScriptString**)gen->GetAddressOfArg(0);
CScriptString *chars = *(CScriptString**)gen->GetAddressOfArg(1);
int start = *(int*)gen->GetAddressOfArg(2);
// Find the substring
int loc = (int)str->buffer.find_first_not_of(chars->buffer, start);
// Return the result
*(int*)gen->GetAddressOfReturnLocation() = loc;
}
void StringFindFirstNotOf0_Generic(asIScriptGeneric *gen)
{
// Get the arguments
CScriptString *str = *(CScriptString**)gen->GetAddressOfArg(0);
CScriptString *chars = *(CScriptString**)gen->GetAddressOfArg(1);
// Find the substring
int loc = (int)str->buffer.find_first_not_of(chars->buffer);
// Return the result
*(int*)gen->GetAddressOfReturnLocation() = loc;
}
// This function returns the index of the last character that is in
// the specified set of characters. If no such character is found -1 is
// returned.
//
// AngelScript signature:
// int findLastOf(const string &in str, const string &in chars, int start)
void StringFindLastOf_Generic(asIScriptGeneric *gen)
{
// Get the arguments
CScriptString *str = *(CScriptString**)gen->GetAddressOfArg(0);
CScriptString *chars = *(CScriptString**)gen->GetAddressOfArg(1);
int start = *(int*)gen->GetAddressOfArg(2);
// Find the substring
int loc = (int)str->buffer.find_last_of(chars->buffer, start);
// Return the result
*(int*)gen->GetAddressOfReturnLocation() = loc;
}
void StringFindLastOf0_Generic(asIScriptGeneric *gen)
{
// Get the arguments
CScriptString *str = *(CScriptString**)gen->GetAddressOfArg(0);
CScriptString *chars = *(CScriptString**)gen->GetAddressOfArg(1);
// Find the substring
int loc = (int)str->buffer.find_last_of(chars->buffer);
// Return the result
*(int*)gen->GetAddressOfReturnLocation() = loc;
}
// This function returns the index of the last character that is not in
// the specified set of characters. If no such character is found -1 is
// returned.
//
// AngelScript signature:
// int findLastNotOf(const string &in str, const string &in chars, int start)
void StringFindLastNotOf_Generic(asIScriptGeneric *gen)
{
// Get the arguments
CScriptString *str = *(CScriptString**)gen->GetAddressOfArg(0);
CScriptString *chars = *(CScriptString**)gen->GetAddressOfArg(1);
int start = *(int*)gen->GetAddressOfArg(2);
// Find the substring
int loc = (int)str->buffer.find_last_not_of(chars->buffer, start);
// Return the result
*(int*)gen->GetAddressOfReturnLocation() = loc;
}
void StringFindLastNotOf0_Generic(asIScriptGeneric *gen)
{
// Get the arguments
CScriptString *str = *(CScriptString**)gen->GetAddressOfArg(0);
CScriptString *chars = *(CScriptString**)gen->GetAddressOfArg(1);
// Find the substring
int loc = (int)str->buffer.find_last_not_of(chars->buffer);
// Return the result
*(int*)gen->GetAddressOfReturnLocation() = loc;
}
// This function takes an input string and splits it into parts by looking
// for a specified delimiter. Example:
//
// string str = "A|B||D";
// string@[]@ array = split(str, "|");
//
// The resulting array has the following elements:
//
// {"A", "B", "", "D"}
//
// AngelScript signature:
// string@[]@ split(const string &in str, const string &in delim)
void StringSplit_Generic(asIScriptGeneric *gen)
{
// Obtain a pointer to the engine
asIScriptContext *ctx = asGetActiveContext();
asIScriptEngine *engine = ctx->GetEngine();
// TODO: This should only be done once
int stringArrayType = engine->GetTypeIdByDecl("string@[]");
// Create the array object
asIScriptArray *array = (asIScriptArray*)engine->CreateScriptObject(stringArrayType);
// Get the arguments
CScriptString *str = *(CScriptString**)gen->GetAddressOfArg(0);
CScriptString *delim = *(CScriptString**)gen->GetAddressOfArg(1);
// Find the existence of the delimiter in the input string
int pos = 0, prev = 0, count = 0;
while( (pos = (int)str->buffer.find(delim->buffer, prev)) != (int)std::string::npos )
{
// Add the part to the array
CScriptString *part = new CScriptString();
part->buffer.assign(&str->buffer[prev], pos-prev);
array->Resize(array->GetElementCount()+1);
*(CScriptString**)array->GetElementPointer(count) = part;
// Find the next part
count++;
prev = pos + (int)delim->buffer.length();
}
// Add the remaining part
CScriptString *part = new CScriptString();
part->buffer.assign(&str->buffer[prev]);
array->Resize(array->GetElementCount()+1);
*(CScriptString**)array->GetElementPointer(count) = part;
// Return the array by handle
*(asIScriptArray**)gen->GetAddressOfReturnLocation() = array;
}
// This function takes as input an array of string handles as well as a
// delimiter and concatenates the array elements into one delimited string.
// Example:
//
// string@[] array = {"A", "B", "", "D"};
// string str = join(array, "|");
//
// The resulting string is:
//
// "A|B||D"
//
// AngelScript signature:
// string@ join(const string@[] &in array, const string &in delim)
void StringJoin_Generic(asIScriptGeneric *gen)
{
// Get the arguments
asIScriptArray *array = *(asIScriptArray**)gen->GetAddressOfArg(0);
CScriptString *delim = *(CScriptString**)gen->GetAddressOfArg(1);
// Create the new string
CScriptString *str = new CScriptString();
int n;
for( n = 0; n < (int)array->GetElementCount() - 1; n++ )
{
CScriptString *part = *(CScriptString**)array->GetElementPointer(n);
str->buffer += part->buffer;
str->buffer += delim->buffer;
}
// Add the last part
CScriptString *part = *(CScriptString**)array->GetElementPointer(n);
str->buffer += part->buffer;
// Return the string
*(CScriptString**)gen->GetAddressOfReturnLocation() = str;
}
// TODO: Implement the following functions
//
// int64 parseInt(const string &in str, int &out bytesParsed);
// double parseDouble(const string &in str, int &out bytesParsed);
// string @ formatString(int64, const string &in format); // should use sprintf to format the string
// string @ formatDouble(double, const string &in format);
//
// int16 byteStringToInt16(const string &in str, int start);
// int32 byteStringToInt32(const string &in str, int start);
// int64 byteStringtoInt64(const string &in str, int start);
// float byteStringToFloat(const string &in str, int start);
// double byteStringToDouble(const string &in str, int start);
// string @ int16ToByteString(int16);
// string @ int32ToByteString(int32);
// string @ int64ToByteString(int64);
// string @ floatToByteString(float);
// string @ doubleToByteString(double);
// This is where the utility functions are registered.
// The string type must have been registered first.
void RegisterScriptStringUtils(asIScriptEngine *engine)
{
int r;
r = engine->RegisterGlobalFunction("string@ substring(const string &in, int, int)", asFUNCTION(StringSubString_Generic), asCALL_GENERIC); assert(r >= 0);
r = engine->RegisterGlobalFunction("int findFirst(const string &in, const string &in)", asFUNCTION(StringFindFirst0_Generic), asCALL_GENERIC); assert(r >= 0);
r = engine->RegisterGlobalFunction("int findFirst(const string &in, const string &in, int)", asFUNCTION(StringFindFirst_Generic), asCALL_GENERIC); assert(r >= 0);
r = engine->RegisterGlobalFunction("int findLast(const string &in, const string &in)", asFUNCTION(StringFindLast0_Generic), asCALL_GENERIC); assert(r >= 0);
r = engine->RegisterGlobalFunction("int findLast(const string &in, const string &in, int)", asFUNCTION(StringFindLast_Generic), asCALL_GENERIC); assert(r >= 0);
r = engine->RegisterGlobalFunction("int findFirstOf(const string &in, const string &in)", asFUNCTION(StringFindFirstOf0_Generic), asCALL_GENERIC); assert(r >= 0);
r = engine->RegisterGlobalFunction("int findFirstOf(const string &in, const string &in, int)", asFUNCTION(StringFindFirstOf_Generic), asCALL_GENERIC); assert(r >= 0);
r = engine->RegisterGlobalFunction("int findFirstNotOf(const string &in, const string &in)", asFUNCTION(StringFindFirstNotOf0_Generic), asCALL_GENERIC); assert(r >= 0);
r = engine->RegisterGlobalFunction("int findFirstNotOf(const string &in, const string &in, int)", asFUNCTION(StringFindFirstNotOf_Generic), asCALL_GENERIC); assert(r >= 0);
r = engine->RegisterGlobalFunction("int findLastOf(const string &in, const string &in)", asFUNCTION(StringFindLastOf0_Generic), asCALL_GENERIC); assert(r >= 0);
r = engine->RegisterGlobalFunction("int findLastOf(const string &in, const string &in, int)", asFUNCTION(StringFindLastOf_Generic), asCALL_GENERIC); assert(r >= 0);
r = engine->RegisterGlobalFunction("int findLastNotOf(const string &in, const string &in)", asFUNCTION(StringFindLastNotOf0_Generic), asCALL_GENERIC); assert(r >= 0);
r = engine->RegisterGlobalFunction("int findLastNotOf(const string &in, const string &in, int)", asFUNCTION(StringFindLastNotOf_Generic), asCALL_GENERIC); assert(r >= 0);
r = engine->RegisterGlobalFunction("string@[]@ split(const string &in, const string &in)", asFUNCTION(StringSplit_Generic), asCALL_GENERIC); assert(r >= 0);
r = engine->RegisterGlobalFunction("string@ join(const string@[] &in, const string &in)", asFUNCTION(StringJoin_Generic), asCALL_GENERIC); assert(r >= 0);
}