1859 lines
68 KiB
C++
1859 lines
68 KiB
C++
/*==============================================================================
|
|
** Copyright (C) 2024-2027 WingSummer
|
|
**
|
|
** This program is free software: you can redistribute it and/or modify it under
|
|
** the terms of the GNU Affero General Public License as published by the Free
|
|
** Software Foundation, version 3.
|
|
**
|
|
** 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 Affero General Public License for more
|
|
** details.
|
|
**
|
|
** You should have received a copy of the GNU Affero General Public License
|
|
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
** =============================================================================
|
|
*/
|
|
|
|
#include "scriptqstring.h"
|
|
#include "AngelScript/sdk/add_on/autowrapper/aswrappedcall.h"
|
|
#include "AngelScript/sdk/add_on/scriptarray/scriptarray.h"
|
|
#include "angelscript.h"
|
|
#include "class/angelscripthelper.h"
|
|
|
|
#include <QHash>
|
|
#include <QMetaEnum>
|
|
#include <QString>
|
|
|
|
BEGIN_AS_NAMESPACE
|
|
typedef std::unordered_map<QString, int> Map_t;
|
|
END_AS_NAMESPACE
|
|
|
|
BEGIN_AS_NAMESPACE
|
|
class CQStringFactory : public asIStringFactory {
|
|
public:
|
|
CQStringFactory() {}
|
|
~CQStringFactory() {
|
|
// The script engine must release each string
|
|
// constant that it has requested
|
|
Q_ASSERT(stringCache.size() == 0);
|
|
}
|
|
|
|
const void *GetStringConstant(const char *data, asUINT length) {
|
|
// The string factory might be modified from multiple
|
|
// threads, so it is necessary to use a mutex.
|
|
asAcquireExclusiveLock();
|
|
|
|
QString str = QString::fromUtf8(QByteArray(data, length));
|
|
|
|
Map_t::iterator it = stringCache.find(str);
|
|
if (it != stringCache.end())
|
|
it->second++;
|
|
else
|
|
it = stringCache.insert(Map_t::value_type(str, 1)).first;
|
|
|
|
asReleaseExclusiveLock();
|
|
|
|
return reinterpret_cast<const void *>(&it->first);
|
|
}
|
|
|
|
int ReleaseStringConstant(const void *str) {
|
|
if (str == 0)
|
|
return asERROR;
|
|
|
|
int ret = asSUCCESS;
|
|
|
|
// The string factory might be modified from multiple
|
|
// threads, so it is necessary to use a mutex.
|
|
asAcquireExclusiveLock();
|
|
auto strv = *reinterpret_cast<const QString *>(str);
|
|
|
|
Map_t::iterator it = stringCache.find(strv);
|
|
if (it == stringCache.end()) {
|
|
// ret = asERROR;
|
|
// TODO: I don't know why invalid string pointer passed to it
|
|
// just ignore it.
|
|
} else {
|
|
it->second--;
|
|
if (it->second == 0)
|
|
stringCache.erase(it);
|
|
}
|
|
|
|
asReleaseExclusiveLock();
|
|
|
|
return ret;
|
|
}
|
|
|
|
int GetRawStringData(const void *str, char *data, asUINT *length) const {
|
|
if (str == 0)
|
|
return asERROR;
|
|
|
|
auto buffer = reinterpret_cast<const QString *>(str)->toUtf8();
|
|
|
|
if (length)
|
|
*length = buffer.length();
|
|
|
|
if (data)
|
|
memcpy(data, buffer.data(), buffer.length());
|
|
|
|
return asSUCCESS;
|
|
}
|
|
|
|
// THe access to the string cache is protected with the common mutex
|
|
// provided by AngelScript
|
|
Map_t stringCache;
|
|
};
|
|
|
|
static CQStringFactory *stringFactory = nullptr;
|
|
|
|
// Make this public so the application can also use the string
|
|
// factory and share the string constants if so desired, or to
|
|
// monitor the size of the string factory cache.
|
|
CQStringFactory *GetQStringFactorySingleton() {
|
|
if (stringFactory == nullptr) {
|
|
// Make sure no other thread is creating the string factory at the same
|
|
// time
|
|
asAcquireExclusiveLock();
|
|
if (stringFactory == nullptr) {
|
|
// The following instance will be destroyed by the global
|
|
// CStdStringFactoryCleaner instance upon application shutdown
|
|
stringFactory = new CQStringFactory();
|
|
}
|
|
asReleaseExclusiveLock();
|
|
}
|
|
return stringFactory;
|
|
}
|
|
|
|
class CQStringFactoryCleaner {
|
|
public:
|
|
~CQStringFactoryCleaner() {
|
|
if (stringFactory) {
|
|
// Only delete the string factory if the stringCache is empty
|
|
// If it is not empty, it means that someone might still attempt
|
|
// to release string constants, so if we delete the string factory
|
|
// the application might crash. Not deleting the cache would
|
|
// lead to a memory leak, but since this is only happens when the
|
|
// application is shutting down anyway, it is not important.
|
|
if (stringFactory->stringCache.empty()) {
|
|
delete stringFactory;
|
|
stringFactory = nullptr;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
Q_GLOBAL_STATIC(CQStringFactoryCleaner, cleaner)
|
|
|
|
static void ConstructString(QString *thisPointer) {
|
|
new (thisPointer) QString();
|
|
}
|
|
|
|
static void ConstructStringChar(const QChar &ch, QString *thisPointer) {
|
|
new (thisPointer) QString(ch);
|
|
}
|
|
|
|
static void CopyConstructString(const QString &other, QString *thisPointer) {
|
|
new (thisPointer) QString(other);
|
|
}
|
|
|
|
static void DestructString(QString *thisPointer) { thisPointer->~QString(); }
|
|
|
|
static QString &AddAssignStringToString(const QString &str, QString &dest) {
|
|
// We don't register the method directly because some compilers
|
|
// and standard libraries inline the definition, resulting in the
|
|
// linker being unable to find the declaration.
|
|
// Example: CLang/LLVM with XCode 4.3 on OSX 10.7
|
|
dest += str;
|
|
return dest;
|
|
}
|
|
|
|
// bool string::isEmpty()
|
|
// bool string::empty() // if AS_USE_STLNAMES == 1
|
|
static bool StringIsEmpty(const QString &str) {
|
|
// We don't register the method directly because some compilers
|
|
// and standard libraries inline the definition, resulting in the
|
|
// linker being unable to find the declaration
|
|
// Example: CLang/LLVM with XCode 4.3 on OSX 10.7
|
|
return str.isEmpty();
|
|
}
|
|
|
|
#if AS_NO_IMPL_OPS_WITH_STRING_AND_PRIMITIVE == 0
|
|
static QString &AssignUInt64ToString(asQWORD i, QString &dest) {
|
|
dest = QString::number(i);
|
|
return dest;
|
|
}
|
|
|
|
static QString &AddAssignUInt64ToString(asQWORD i, QString &dest) {
|
|
dest += QString::number(i);
|
|
return dest;
|
|
}
|
|
|
|
static QString AddStringUInt64(const QString &str, asQWORD i) {
|
|
return str + QString::number(i);
|
|
}
|
|
|
|
static QString AddInt64String(asINT64 i, const QString &str) {
|
|
return QString::number(i) + str;
|
|
}
|
|
|
|
static QString &AssignInt64ToString(asINT64 i, QString &dest) {
|
|
dest = QString::number(i);
|
|
return dest;
|
|
}
|
|
|
|
static QString &AddAssignInt64ToString(asINT64 i, QString &dest) {
|
|
dest += QString::number(i);
|
|
return dest;
|
|
}
|
|
|
|
static QString AddStringInt64(const QString &str, asINT64 i) {
|
|
return str + QString::number(i);
|
|
}
|
|
|
|
static QString AddUInt64String(asQWORD i, const QString &str) {
|
|
return QString::number(i) + str;
|
|
}
|
|
|
|
static QString &AssignDoubleToString(double f, QString &dest) {
|
|
dest = QString::number(f);
|
|
return dest;
|
|
}
|
|
|
|
static QString &AddAssignDoubleToString(double f, QString &dest) {
|
|
dest += QString::number(f);
|
|
return dest;
|
|
}
|
|
|
|
static QString &AssignFloatToString(float f, QString &dest) {
|
|
dest = QString::number(f);
|
|
return dest;
|
|
}
|
|
|
|
static QString &AddAssignFloatToString(float f, QString &dest) {
|
|
dest += QString::number(f);
|
|
return dest;
|
|
}
|
|
|
|
static QString &AssignCharToString(const QChar &ch, QString &dest) {
|
|
dest = ch;
|
|
return dest;
|
|
}
|
|
|
|
static QString &AddAssignCharToString(const QChar &ch, QString &dest) {
|
|
dest += ch;
|
|
return dest;
|
|
}
|
|
|
|
static QString &AssignBoolToString(bool b, QString &dest) {
|
|
dest = b ? QStringLiteral("true") : QStringLiteral("false");
|
|
return dest;
|
|
}
|
|
|
|
static QString &AddAssignBoolToString(bool b, QString &dest) {
|
|
dest += b ? QStringLiteral("true") : QStringLiteral("false");
|
|
return dest;
|
|
}
|
|
|
|
static QString AddStringDouble(const QString &str, double f) {
|
|
return str + QString::number(f);
|
|
}
|
|
|
|
static QString AddDoubleString(double f, const QString &str) {
|
|
return QString::number(f) + str;
|
|
}
|
|
|
|
static QString AddStringFloat(const QString &str, float f) {
|
|
return str + QString::number(f);
|
|
}
|
|
|
|
static QString AddFloatString(float f, const QString &str) {
|
|
return QString::number(f) + str;
|
|
}
|
|
|
|
static QString AddStringChar(const QString &str, const QChar &ch) {
|
|
return str + ch;
|
|
}
|
|
|
|
static QString AddCharString(const QChar &ch, const QString &str) {
|
|
return ch + str;
|
|
}
|
|
|
|
static QString AddStringBool(const QString &str, bool b) {
|
|
return str + (b ? QStringLiteral("true") : QStringLiteral("false"));
|
|
}
|
|
|
|
static QString AddBoolString(bool b, const QString &str) {
|
|
return (b ? QStringLiteral("true") : QStringLiteral("false")) + str;
|
|
}
|
|
#endif
|
|
|
|
static QChar *StringCharAt(unsigned int i, QString &str) {
|
|
if (asDWORD(i) >= asDWORD(str.size())) {
|
|
// Set a script exception
|
|
asIScriptContext *ctx = asGetActiveContext();
|
|
ctx->SetException("Out of range");
|
|
|
|
// Return a null pointer
|
|
return nullptr;
|
|
}
|
|
|
|
return str.data() + i;
|
|
}
|
|
|
|
// AngelScript signature:
|
|
// int string::opCmp(const string &in) const
|
|
static int StringCmp(const QString &a, const QString &b) {
|
|
int cmp = 0;
|
|
if (a < b)
|
|
cmp = -1;
|
|
else if (a > b)
|
|
cmp = 1;
|
|
return cmp;
|
|
}
|
|
|
|
// 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 string::findFirst(const string &in sub, uint start = 0) const
|
|
static int StringFindFirst(const QString &sub, asUINT start,
|
|
const QString &str) {
|
|
// We don't register the method directly because the argument types change
|
|
// between 32bit and 64bit platforms
|
|
return (int)str.indexOf(sub, start);
|
|
}
|
|
|
|
// This function returns the index of the first position where the one of the
|
|
// bytes in substring exists in the input string. If the characters in the
|
|
// substring doesn't exist in the input string -1 is returned.
|
|
//
|
|
// AngelScript signature:
|
|
// int string::findFirstOf(const string &in sub, uint start = 0) const
|
|
static int StringFindFirstOf(const QString &sub, asUINT start,
|
|
const QString &str) {
|
|
// We don't register the method directly because the argument types change
|
|
// between 32bit and 64bit platforms
|
|
return (int)str.indexOf(sub, start);
|
|
}
|
|
|
|
// This function returns the index of the last position where the one of the
|
|
// bytes in substring exists in the input string. If the characters in the
|
|
// substring doesn't exist in the input string -1 is returned.
|
|
//
|
|
// AngelScript signature:
|
|
// int string::findLastOf(const string &in sub, uint start = -1) const
|
|
static int StringFindLastOf(const QString &sub, asUINT start,
|
|
const QString &str) {
|
|
// We don't register the method directly because the argument types change
|
|
// between 32bit and 64bit platforms
|
|
return (int)str.lastIndexOf(sub, start);
|
|
}
|
|
|
|
// AngelScript signature:
|
|
// void string::insert(uint pos, const string &in other)
|
|
static void StringInsert(unsigned int pos, const QString &other, QString &str) {
|
|
// We don't register the method directly because the argument types change
|
|
// between 32bit and 64bit platforms
|
|
str.insert(pos, other);
|
|
}
|
|
|
|
// AngelScript signature:
|
|
// void string::erase(uint pos, int count = -1)
|
|
static void StringErase(unsigned int pos, int count, QString &str) {
|
|
// We don't register the method directly because the argument types change
|
|
// between 32bit and 64bit platforms
|
|
str.remove(pos, count);
|
|
}
|
|
|
|
// AngelScript signature:
|
|
// uint string::length() const
|
|
static asUINT StringLength(const QString &str) {
|
|
// We don't register the method directly because the return type changes
|
|
// between 32bit and 64bit platforms
|
|
return (asUINT)str.length();
|
|
}
|
|
|
|
// AngelScript signature:
|
|
// void string::resize(uint l)
|
|
static void StringResize(asUINT l, QString &str) {
|
|
// We don't register the method directly because the argument types change
|
|
// between 32bit and 64bit platforms
|
|
str.resize(l);
|
|
}
|
|
|
|
// AngelScript signature:
|
|
// string formatInt(int64 val, const string &in options)
|
|
static QString formatInt(asINT64 value, const QString &options) {
|
|
return QString::asprintf(options.toLatin1(), value);
|
|
}
|
|
|
|
// AngelScript signature:
|
|
// string formatUInt(uint64 val, const string &in options)
|
|
static QString formatUInt(asQWORD value, const QString &options) {
|
|
return QString::asprintf(options.toLatin1(), value);
|
|
}
|
|
|
|
// AngelScript signature:
|
|
// string formatFloat(double val, const string &in options, uint width, uint
|
|
// precision)
|
|
static QString formatFloat(double value, const QString &options) {
|
|
return QString::asprintf(options.toLatin1(), value);
|
|
}
|
|
|
|
// AngelScript signature:
|
|
// int64 parseInt(const string &in val, uint base = 10, uint &out byteCount = 0)
|
|
static asINT64 parseInt(const QString &val, asUINT base, asUINT *byteCount) {
|
|
Q_UNUSED(byteCount);
|
|
return val.toInt(nullptr, base);
|
|
}
|
|
|
|
// AngelScript signature:
|
|
// uint64 parseUInt(const string &in val, uint base = 10, bool &out ok =
|
|
// 0)
|
|
static asQWORD parseUInt(const QString &val, asUINT base, bool *ok) {
|
|
return val.toUInt(ok, base);
|
|
}
|
|
|
|
// AngelScript signature:
|
|
// double parseFloat(const string &in val, uint &out byteCount = 0)
|
|
double parseFloat(const QString &val, bool *ok) { return val.toFloat(ok); }
|
|
|
|
// This function returns a string containing the substring of the input string
|
|
// determined by the starting index and count of characters.
|
|
//
|
|
// AngelScript signature:
|
|
// string string::substr(uint start = 0, int count = -1) const
|
|
static QString StringSubString(asUINT start, int count, const QString &str) {
|
|
return str.mid(start, count);
|
|
}
|
|
|
|
// String equality comparison.
|
|
// Returns true iff lhs is equal to rhs.
|
|
//
|
|
// For some reason gcc 4.7 has difficulties resolving the
|
|
// asFUNCTIONPR(operator==, (const string &, const string &)
|
|
// makro, so this wrapper was introduced as work around.
|
|
static bool StringEquals(const QString &lhs, const QString &rhs) {
|
|
return lhs == rhs;
|
|
}
|
|
|
|
//=================================================
|
|
// some functions ADDITIONALLY exported by wingsummer
|
|
|
|
// int compare(const string &in val, bool caseSensitive = true) const
|
|
static int stringCompare(const QString &other, bool caseSensitive,
|
|
const QString &str) {
|
|
return str.compare(other,
|
|
caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive);
|
|
}
|
|
|
|
// bool contains(const string &in val, bool caseSensitive = true) const
|
|
static bool stringContains(const QString &lhs, bool caseSensitive,
|
|
const QString &str) {
|
|
return str.contains(lhs, caseSensitive ? Qt::CaseSensitive
|
|
: Qt::CaseInsensitive);
|
|
}
|
|
|
|
// bool endsWith(const string &in val, bool caseSensitive = true) const
|
|
static bool stringEndsWith(const QString &lhs, bool caseSensitive,
|
|
const QString &str) {
|
|
return str.endsWith(lhs, caseSensitive ? Qt::CaseSensitive
|
|
: Qt::CaseInsensitive);
|
|
}
|
|
|
|
// string repeated(qsizetype times)
|
|
static QString stringRepeated(qsizetype times, const QString &str) {
|
|
return str.repeated(times);
|
|
}
|
|
|
|
// string replace(const string &in before,const string &in after,
|
|
// bool caseSensitive = true)
|
|
static QString stringReplace(const QString &before, const QString &after,
|
|
bool caseSensitive, QString &str) {
|
|
return str.replace(before, after,
|
|
caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive);
|
|
}
|
|
|
|
// string simplified()
|
|
static QString stringSimplified(const QString &str) { return str.simplified(); }
|
|
|
|
// bool startsWith(const string &in substr, bool caseSensitive = true)
|
|
static bool stringStartsWith(const QString &substr, bool caseSensitive,
|
|
const QString &str) {
|
|
return str.startsWith(substr, caseSensitive ? Qt::CaseSensitive
|
|
: Qt::CaseInsensitive);
|
|
}
|
|
|
|
// array<string>@ split(const QString &sep, bool skipEmpty = false,
|
|
// bool caseSensitive = true)
|
|
static CScriptArray *stringSplit(const QString &sep, bool skipEmpty,
|
|
bool caseSensitive, const QString &str) {
|
|
return retarrayWrapperFunction(
|
|
[&]() -> QStringList {
|
|
return str.split(
|
|
sep, skipEmpty ? Qt::SkipEmptyParts : Qt::KeepEmptyParts,
|
|
caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive);
|
|
},
|
|
"array<string>");
|
|
}
|
|
|
|
//=================================================
|
|
|
|
static void ConstructChar(QChar *thisPointer) { new (thisPointer) QChar(); }
|
|
|
|
static void ConstructCharInt(int v, QChar *thisPointer) {
|
|
new (thisPointer) QChar(v);
|
|
}
|
|
|
|
static void ConstructCharString(QString *v, QChar *thisPointer) {
|
|
if (v->isEmpty()) {
|
|
new (thisPointer) QChar();
|
|
} else {
|
|
new (thisPointer) QChar(v->at(0));
|
|
}
|
|
}
|
|
|
|
static void CopyConstructChar(const QChar &other, QChar *thisPointer) {
|
|
new (thisPointer) QChar(other);
|
|
}
|
|
|
|
static void DestructChar(QChar *thisPointer) { thisPointer->~QChar(); }
|
|
|
|
//=================================================
|
|
|
|
void RegisterQString_Native(asIScriptEngine *engine) {
|
|
int r = 0;
|
|
Q_UNUSED(r);
|
|
|
|
// register the char type
|
|
r = engine->RegisterObjectType("char", sizeof(QChar),
|
|
asOBJ_VALUE | asOBJ_APP_CLASS_ALLINTS |
|
|
asGetTypeTraits<QChar>());
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectBehaviour("char", asBEHAVE_CONSTRUCT, "void f()",
|
|
asFUNCTION(ConstructChar),
|
|
asCALL_CDECL_OBJFIRST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectBehaviour(
|
|
"char", asBEHAVE_CONSTRUCT, "void f(int)", asFUNCTION(ConstructCharInt),
|
|
asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
|
|
r = engine->RegisterObjectBehaviour(
|
|
"char", asBEHAVE_CONSTRUCT, "void f(const char &in)",
|
|
asFUNCTION(CopyConstructChar), asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
|
|
r = engine->RegisterObjectBehaviour("char", asBEHAVE_DESTRUCT, "void f()",
|
|
asFUNCTION(DestructChar),
|
|
asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
|
|
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
|
r = engine->RegisterObjectMethod(
|
|
"char", "int16 unicode() const",
|
|
asMETHODPR(QChar, unicode, () const, ushort), asCALL_THISCALL);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
#else
|
|
r = engine->RegisterObjectMethod(
|
|
"char", "int16 unicode() const",
|
|
asMETHODPR(QChar, unicode, () const, char16_t), asCALL_THISCALL);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
#endif
|
|
|
|
r = engine->RegisterObjectMethod(
|
|
"char", "char &opAssign(const char &in)",
|
|
asMETHODPR(QChar, operator=, (const QChar &), QChar &),
|
|
asCALL_THISCALL);
|
|
Q_UNUSED(r);
|
|
Q_ASSERT(r >= 0);
|
|
|
|
// Register the string type
|
|
#if AS_CAN_USE_CPP11
|
|
// With C++11 it is possible to use asGetTypeTraits to automatically
|
|
// determine the correct flags to use
|
|
r = engine->RegisterObjectType("string", sizeof(QString),
|
|
asOBJ_VALUE | asGetTypeTraits<QString>());
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
#else
|
|
r = engine->RegisterObjectType("string", sizeof(QString),
|
|
asOBJ_VALUE | asOBJ_APP_CLASS_CDAK);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
#endif
|
|
|
|
r = engine->RegisterObjectBehaviour(
|
|
"char", asBEHAVE_CONSTRUCT, "void f(const string &in)",
|
|
asFUNCTION(ConstructCharString), asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
|
|
r = engine->RegisterStringFactory("string", GetQStringFactorySingleton());
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
|
|
// Register the object operator overloads
|
|
r = engine->RegisterObjectBehaviour("string", asBEHAVE_CONSTRUCT,
|
|
"void f()", asFUNCTION(ConstructString),
|
|
asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectBehaviour(
|
|
"string", asBEHAVE_CONSTRUCT, "void f(const string &in)",
|
|
asFUNCTION(CopyConstructString), asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectBehaviour("string", asBEHAVE_DESTRUCT, "void f()",
|
|
asFUNCTION(DestructString),
|
|
asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectBehaviour(
|
|
"string", asBEHAVE_CONSTRUCT, "void f(const char &in)",
|
|
asFUNCTION(ConstructStringChar), asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod(
|
|
"string", "string &opAssign(const string &in)",
|
|
asMETHODPR(QString, operator=, (const QString &), QString &),
|
|
asCALL_THISCALL);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
// Need to use a wrapper on Mac OS X 10.7/XCode 4.3 and CLang/LLVM,
|
|
// otherwise the linker fails
|
|
r = engine->RegisterObjectMethod(
|
|
"string", "string &opAddAssign(const string &in)",
|
|
asFUNCTION(AddAssignStringToString), asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
// r = engine->RegisterObjectMethod("string", "string &opAddAssign(const
|
|
// string &in)", asMETHODPR(string, operator+=, (const string&), string&),
|
|
// asCALL_THISCALL); Q_ASSERT( r >= 0 );
|
|
|
|
// Need to use a wrapper for operator== otherwise gcc 4.7 fails to compile
|
|
r = engine->RegisterObjectMethod(
|
|
"string", "bool opEquals(const string &in) const",
|
|
asFUNCTIONPR(StringEquals, (const QString &, const QString &), bool),
|
|
asCALL_CDECL_OBJFIRST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod(
|
|
"string", "int opCmp(const string &in) const", asFUNCTION(StringCmp),
|
|
asCALL_CDECL_OBJFIRST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
|
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
|
r = engine->RegisterObjectMethod(
|
|
"string", "string opAdd(const string &in) const",
|
|
asFUNCTIONPR(operator+, (const QString &, const QString &), QString),
|
|
asCALL_CDECL_OBJFIRST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
#else
|
|
r = engine->RegisterObjectMethod(
|
|
"string", "string opAdd(const string &in) const",
|
|
asFUNCTIONPR(operator+, (const QString &, const QString &),
|
|
const QString),
|
|
asCALL_CDECL_OBJFIRST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
#endif
|
|
|
|
// The string length can be accessed through methods or through virtual
|
|
// property
|
|
#if AS_USE_ACCESSORS != 1
|
|
r = engine->RegisterObjectMethod("string", "uint length() const",
|
|
asFUNCTION(StringLength),
|
|
asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
#endif
|
|
r = engine->RegisterObjectMethod("string", "void resize(uint)",
|
|
asFUNCTION(StringResize),
|
|
asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
#if AS_USE_ACCESSORS == 1
|
|
// Don't register these if STL names is used, as they conflict with the
|
|
// method size()
|
|
r = engine->RegisterObjectMethod(
|
|
"string", "uint get_length() const property", asFUNCTION(StringLength),
|
|
asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod("string", "void set_length(uint) property",
|
|
asFUNCTION(StringResize),
|
|
asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
#endif
|
|
// Need to use a wrapper on Mac OS X 10.7/XCode 4.3 and CLang/LLVM,
|
|
// otherwise the linker fails
|
|
// r = engine->RegisterObjectMethod("string", "bool isEmpty() const",
|
|
// asMETHOD(string, empty), asCALL_THISCALL); Q_ASSERT( r >= 0 );
|
|
r = engine->RegisterObjectMethod("string", "bool isEmpty() const",
|
|
asFUNCTION(StringIsEmpty),
|
|
asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
|
|
// Register the index operator, both as a mutator and as an inspector
|
|
// Note that we don't register the operator[] directly, as it doesn't do
|
|
// bounds checking
|
|
r = engine->RegisterObjectMethod("string", "char &opIndex(uint)",
|
|
asFUNCTION(StringCharAt),
|
|
asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod(
|
|
"string", "const char &opIndex(uint) const", asFUNCTION(StringCharAt),
|
|
asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
|
|
#if AS_NO_IMPL_OPS_WITH_STRING_AND_PRIMITIVE == 0
|
|
// Automatic conversion from values
|
|
r = engine->RegisterObjectMethod("string", "string &opAssign(double)",
|
|
asFUNCTION(AssignDoubleToString),
|
|
asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod("string", "string &opAddAssign(double)",
|
|
asFUNCTION(AddAssignDoubleToString),
|
|
asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod("string", "string opAdd(double) const",
|
|
asFUNCTION(AddStringDouble),
|
|
asCALL_CDECL_OBJFIRST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod("string", "string opAdd_r(double) const",
|
|
asFUNCTION(AddDoubleString),
|
|
asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
|
|
r = engine->RegisterObjectMethod(
|
|
"string", "string &opAssign(const char &in)",
|
|
asFUNCTION(AssignCharToString), asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod(
|
|
"string", "string &opAddAssign(const char &in)",
|
|
asFUNCTION(AddAssignCharToString), asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod(
|
|
"string", "string opAdd(const char &in) const",
|
|
asFUNCTION(AddStringChar), asCALL_CDECL_OBJFIRST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod(
|
|
"string", "string opAdd_r(const char &in) const",
|
|
asFUNCTION(AddCharString), asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
|
|
r = engine->RegisterObjectMethod("string", "string &opAssign(float)",
|
|
asFUNCTION(AssignCharToString),
|
|
asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod("string", "string &opAddAssign(float)",
|
|
asFUNCTION(AddAssignFloatToString),
|
|
asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod("string", "string opAdd(float) const",
|
|
asFUNCTION(AddStringFloat),
|
|
asCALL_CDECL_OBJFIRST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod("string", "string opAdd_r(float) const",
|
|
asFUNCTION(AddFloatString),
|
|
asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
|
|
r = engine->RegisterObjectMethod("string", "string &opAssign(int64)",
|
|
asFUNCTION(AssignInt64ToString),
|
|
asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod("string", "string &opAddAssign(int64)",
|
|
asFUNCTION(AddAssignInt64ToString),
|
|
asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod("string", "string opAdd(int64) const",
|
|
asFUNCTION(AddStringInt64),
|
|
asCALL_CDECL_OBJFIRST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod("string", "string opAdd_r(int64) const",
|
|
asFUNCTION(AddInt64String),
|
|
asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
|
|
r = engine->RegisterObjectMethod("string", "string &opAssign(uint64)",
|
|
asFUNCTION(AssignUInt64ToString),
|
|
asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod("string", "string &opAddAssign(uint64)",
|
|
asFUNCTION(AddAssignUInt64ToString),
|
|
asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod("string", "string opAdd(uint64) const",
|
|
asFUNCTION(AddStringUInt64),
|
|
asCALL_CDECL_OBJFIRST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod("string", "string opAdd_r(uint64) const",
|
|
asFUNCTION(AddUInt64String),
|
|
asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
|
|
r = engine->RegisterObjectMethod("string", "string &opAssign(bool)",
|
|
asFUNCTION(AssignBoolToString),
|
|
asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod("string", "string &opAddAssign(bool)",
|
|
asFUNCTION(AddAssignBoolToString),
|
|
asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod("string", "string opAdd(bool) const",
|
|
asFUNCTION(AddStringBool),
|
|
asCALL_CDECL_OBJFIRST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod("string", "string opAdd_r(bool) const",
|
|
asFUNCTION(AddBoolString),
|
|
asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
#endif
|
|
|
|
// Utilities
|
|
r = engine->RegisterObjectMethod(
|
|
"string", "string substr(uint start = 0, int count = -1) const",
|
|
asFUNCTION(StringSubString), asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod(
|
|
"string", "int findFirst(const string &in, uint start = 0) const",
|
|
asFUNCTION(StringFindFirst), asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod(
|
|
"string", "int findFirstOf(const string &in, uint start = 0) const",
|
|
asFUNCTION(StringFindFirstOf), asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
|
|
r = engine->RegisterObjectMethod(
|
|
"string", "void insert(uint pos, const string &in other)",
|
|
asFUNCTION(StringInsert), asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod(
|
|
"string", "void erase(uint pos, int count = -1)",
|
|
asFUNCTION(StringErase), asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
|
|
/* These following things are not avaliable for generic call
|
|
* because it needs a lot of wrapper to do
|
|
* while WingHexExplorer only needs native call
|
|
* (by wingsummer)
|
|
* PULL REQUESTS ARE WELCOMED IF YOU WANT TO ADD GENERIC CALL
|
|
*/
|
|
r = engine->RegisterObjectMethod(
|
|
"string",
|
|
"int compare(const string &in val, bool caseSensitive = true) const",
|
|
asFUNCTION(stringCompare), asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod(
|
|
"string",
|
|
"bool contains(const string &in val, bool caseSensitive = true) const",
|
|
asFUNCTION(stringContains), asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod(
|
|
"string",
|
|
"bool endsWith(const string &in val, bool caseSensitive = true) const",
|
|
asFUNCTION(stringEndsWith), asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod(
|
|
"string", "string repeated(" QSIZETYPE " times)",
|
|
asFUNCTION(stringRepeated), asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod(
|
|
"string",
|
|
"string replace(const string &in before,const string &in after, "
|
|
"bool caseSensitive = true)",
|
|
asFUNCTION(stringReplace), asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod("string", "string simplified()",
|
|
asFUNCTION(stringSimplified),
|
|
asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod(
|
|
"string",
|
|
"bool startsWith(const string &in, bool caseSensitive = true)",
|
|
asFUNCTION(stringStartsWith), asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod(
|
|
"string",
|
|
"array<string>@ split(const string &in, bool skipEmpty = false, "
|
|
"bool caseSensitive = true)",
|
|
asFUNCTION(stringSplit), asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
|
|
r = engine->SetDefaultNamespace("string");
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterGlobalFunction(
|
|
"string formatInt(int64 val, const string &in options = \"\", uint "
|
|
"width = 0)",
|
|
asFUNCTION(formatInt), asCALL_CDECL);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterGlobalFunction(
|
|
"string formatUInt(uint64 val, const string &in options = \"\", uint "
|
|
"width = 0)",
|
|
asFUNCTION(formatUInt), asCALL_CDECL);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterGlobalFunction(
|
|
"string formatFloat(double val, const string &in options = \"\", uint "
|
|
"width = 0, uint precision = 0)",
|
|
asFUNCTION(formatFloat), asCALL_CDECL);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterGlobalFunction("int64 parseInt(const string &in, uint "
|
|
"base = 10, uint &out byteCount = 0)",
|
|
asFUNCTION(parseInt), asCALL_CDECL);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterGlobalFunction(
|
|
"uint64 parseUInt(const string &in, uint base = 10, uint &out "
|
|
"byteCount = 0)",
|
|
asFUNCTION(parseUInt), asCALL_CDECL);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterGlobalFunction(
|
|
"double parseFloat(const string &in, uint &out byteCount = 0)",
|
|
asFUNCTION(parseFloat), asCALL_CDECL);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
engine->SetDefaultNamespace("");
|
|
}
|
|
|
|
static void ConstructStringGeneric(asIScriptGeneric *gen) {
|
|
new (gen->GetObject()) QString();
|
|
}
|
|
|
|
static void CopyConstructStringGeneric(asIScriptGeneric *gen) {
|
|
QString *a = static_cast<QString *>(gen->GetArgObject(0));
|
|
new (gen->GetObject()) QString(*a);
|
|
}
|
|
|
|
static void DestructStringGeneric(asIScriptGeneric *gen) {
|
|
QString *ptr = static_cast<QString *>(gen->GetObject());
|
|
ptr->~QString();
|
|
}
|
|
|
|
static void AssignStringGeneric(asIScriptGeneric *gen) {
|
|
QString *a = static_cast<QString *>(gen->GetArgObject(0));
|
|
QString *self = static_cast<QString *>(gen->GetObject());
|
|
*self = *a;
|
|
gen->SetReturnAddress(self);
|
|
}
|
|
|
|
static void AddAssignStringGeneric(asIScriptGeneric *gen) {
|
|
QString *a = static_cast<QString *>(gen->GetArgObject(0));
|
|
QString *self = static_cast<QString *>(gen->GetObject());
|
|
*self += *a;
|
|
gen->SetReturnAddress(self);
|
|
}
|
|
|
|
static void StringEqualsGeneric(asIScriptGeneric *gen) {
|
|
QString *a = static_cast<QString *>(gen->GetObject());
|
|
QString *b = static_cast<QString *>(gen->GetArgAddress(0));
|
|
*(bool *)gen->GetAddressOfReturnLocation() = (*a == *b);
|
|
}
|
|
|
|
static void StringCmpGeneric(asIScriptGeneric *gen) {
|
|
QString *a = static_cast<QString *>(gen->GetObject());
|
|
QString *b = static_cast<QString *>(gen->GetArgAddress(0));
|
|
|
|
int cmp = 0;
|
|
if (*a < *b)
|
|
cmp = -1;
|
|
else if (*a > *b)
|
|
cmp = 1;
|
|
|
|
*(int *)gen->GetAddressOfReturnLocation() = cmp;
|
|
}
|
|
|
|
static void StringAddGeneric(asIScriptGeneric *gen) {
|
|
QString *a = static_cast<QString *>(gen->GetObject());
|
|
QString *b = static_cast<QString *>(gen->GetArgAddress(0));
|
|
QString ret_val = *a + *b;
|
|
gen->SetReturnObject(&ret_val);
|
|
}
|
|
|
|
static void StringLengthGeneric(asIScriptGeneric *gen) {
|
|
QString *self = static_cast<QString *>(gen->GetObject());
|
|
*static_cast<asUINT *>(gen->GetAddressOfReturnLocation()) =
|
|
(asUINT)self->length();
|
|
}
|
|
|
|
static void StringIsEmptyGeneric(asIScriptGeneric *gen) {
|
|
QString *self = reinterpret_cast<QString *>(gen->GetObject());
|
|
*reinterpret_cast<bool *>(gen->GetAddressOfReturnLocation()) =
|
|
StringIsEmpty(*self);
|
|
}
|
|
|
|
static void StringResizeGeneric(asIScriptGeneric *gen) {
|
|
QString *self = static_cast<QString *>(gen->GetObject());
|
|
self->resize(*static_cast<asUINT *>(gen->GetAddressOfArg(0)));
|
|
}
|
|
|
|
static void StringInsert_Generic(asIScriptGeneric *gen) {
|
|
QString *self = static_cast<QString *>(gen->GetObject());
|
|
asUINT pos = gen->GetArgDWord(0);
|
|
QString *other = reinterpret_cast<QString *>(gen->GetArgAddress(1));
|
|
StringInsert(pos, *other, *self);
|
|
}
|
|
|
|
static void StringErase_Generic(asIScriptGeneric *gen) {
|
|
QString *self = static_cast<QString *>(gen->GetObject());
|
|
asUINT pos = gen->GetArgDWord(0);
|
|
int count = int(gen->GetArgDWord(1));
|
|
StringErase(pos, count, *self);
|
|
}
|
|
|
|
static void StringFindFirst_Generic(asIScriptGeneric *gen) {
|
|
QString *find = reinterpret_cast<QString *>(gen->GetArgAddress(0));
|
|
asUINT start = gen->GetArgDWord(1);
|
|
QString *self = reinterpret_cast<QString *>(gen->GetObject());
|
|
*reinterpret_cast<int *>(gen->GetAddressOfReturnLocation()) =
|
|
StringFindFirst(*find, start, *self);
|
|
}
|
|
|
|
static void StringFindFirstOf_Generic(asIScriptGeneric *gen) {
|
|
QString *find = reinterpret_cast<QString *>(gen->GetArgAddress(0));
|
|
asUINT start = gen->GetArgDWord(1);
|
|
QString *self = reinterpret_cast<QString *>(gen->GetObject());
|
|
*reinterpret_cast<int *>(gen->GetAddressOfReturnLocation()) =
|
|
StringFindFirstOf(*find, start, *self);
|
|
}
|
|
|
|
static void StringFindLastOf_Generic(asIScriptGeneric *gen) {
|
|
QString *find = reinterpret_cast<QString *>(gen->GetArgAddress(0));
|
|
asUINT start = gen->GetArgDWord(1);
|
|
QString *self = reinterpret_cast<QString *>(gen->GetObject());
|
|
*reinterpret_cast<int *>(gen->GetAddressOfReturnLocation()) =
|
|
StringFindLastOf(*find, start, *self);
|
|
}
|
|
|
|
static void formatInt_Generic(asIScriptGeneric *gen) {
|
|
asINT64 val = gen->GetArgQWord(0);
|
|
QString *options = reinterpret_cast<QString *>(gen->GetArgAddress(1));
|
|
new (gen->GetAddressOfReturnLocation()) QString(formatInt(val, *options));
|
|
}
|
|
|
|
static void formatUInt_Generic(asIScriptGeneric *gen) {
|
|
asQWORD val = gen->GetArgQWord(0);
|
|
QString *options = reinterpret_cast<QString *>(gen->GetArgAddress(1));
|
|
new (gen->GetAddressOfReturnLocation()) QString(formatUInt(val, *options));
|
|
}
|
|
|
|
static void formatFloat_Generic(asIScriptGeneric *gen) {
|
|
double val = gen->GetArgDouble(0);
|
|
QString *options = reinterpret_cast<QString *>(gen->GetArgAddress(1));
|
|
new (gen->GetAddressOfReturnLocation()) QString(formatFloat(val, *options));
|
|
}
|
|
|
|
static void parseInt_Generic(asIScriptGeneric *gen) {
|
|
QString *str = reinterpret_cast<QString *>(gen->GetArgAddress(0));
|
|
asUINT base = gen->GetArgDWord(1);
|
|
asUINT *byteCount = reinterpret_cast<asUINT *>(gen->GetArgAddress(2));
|
|
gen->SetReturnQWord(parseInt(*str, base, byteCount));
|
|
}
|
|
|
|
static void parseUInt_Generic(asIScriptGeneric *gen) {
|
|
QString *str = reinterpret_cast<QString *>(gen->GetArgAddress(0));
|
|
asUINT base = gen->GetArgDWord(1);
|
|
bool *ok = reinterpret_cast<bool *>(gen->GetArgAddress(2));
|
|
gen->SetReturnQWord(parseUInt(*str, base, ok));
|
|
}
|
|
|
|
static void parseFloat_Generic(asIScriptGeneric *gen) {
|
|
QString *str = reinterpret_cast<QString *>(gen->GetArgAddress(0));
|
|
bool *ok = reinterpret_cast<bool *>(gen->GetArgAddress(1));
|
|
gen->SetReturnDouble(parseFloat(*str, ok));
|
|
}
|
|
|
|
static void StringCharAtGeneric(asIScriptGeneric *gen) {
|
|
asDWORD index = gen->GetArgDWord(0);
|
|
QString *self = static_cast<QString *>(gen->GetObject());
|
|
|
|
if (index >= asDWORD(self->size())) {
|
|
// Set a script exception
|
|
asIScriptContext *ctx = asGetActiveContext();
|
|
ctx->SetException("Out of range");
|
|
|
|
gen->SetReturnAddress(0);
|
|
} else {
|
|
gen->SetReturnAddress(&self[index]);
|
|
}
|
|
}
|
|
|
|
#if AS_NO_IMPL_OPS_WITH_STRING_AND_PRIMITIVE == 0
|
|
static void AssignInt2StringGeneric(asIScriptGeneric *gen) {
|
|
asINT64 *a = static_cast<asINT64 *>(gen->GetAddressOfArg(0));
|
|
QString *self = static_cast<QString *>(gen->GetObject());
|
|
*self = QString::number(*a);
|
|
gen->SetReturnAddress(self);
|
|
}
|
|
|
|
static void AssignUInt2StringGeneric(asIScriptGeneric *gen) {
|
|
asQWORD *a = static_cast<asQWORD *>(gen->GetAddressOfArg(0));
|
|
QString *self = static_cast<QString *>(gen->GetObject());
|
|
*self = QString::number(*a);
|
|
gen->SetReturnAddress(self);
|
|
}
|
|
|
|
static void AssignDouble2StringGeneric(asIScriptGeneric *gen) {
|
|
double *a = static_cast<double *>(gen->GetAddressOfArg(0));
|
|
QString *self = static_cast<QString *>(gen->GetObject());
|
|
*self = QString::number(*a);
|
|
gen->SetReturnAddress(self);
|
|
}
|
|
|
|
static void AssignFloat2StringGeneric(asIScriptGeneric *gen) {
|
|
float *a = static_cast<float *>(gen->GetAddressOfArg(0));
|
|
QString *self = static_cast<QString *>(gen->GetObject());
|
|
*self = QString::number(*a);
|
|
gen->SetReturnAddress(self);
|
|
}
|
|
|
|
static void AssignBool2StringGeneric(asIScriptGeneric *gen) {
|
|
bool *a = static_cast<bool *>(gen->GetAddressOfArg(0));
|
|
QString *self = static_cast<QString *>(gen->GetObject());
|
|
*self = *a ? QStringLiteral("true") : QStringLiteral("false");
|
|
gen->SetReturnAddress(self);
|
|
}
|
|
|
|
static void AddAssignDouble2StringGeneric(asIScriptGeneric *gen) {
|
|
double *a = static_cast<double *>(gen->GetAddressOfArg(0));
|
|
QString *self = static_cast<QString *>(gen->GetObject());
|
|
*self += QString::number(*a);
|
|
gen->SetReturnAddress(self);
|
|
}
|
|
|
|
static void AddAssignFloat2StringGeneric(asIScriptGeneric *gen) {
|
|
float *a = static_cast<float *>(gen->GetAddressOfArg(0));
|
|
QString *self = static_cast<QString *>(gen->GetObject());
|
|
*self += QString::number(*a);
|
|
gen->SetReturnAddress(self);
|
|
}
|
|
|
|
static void AddAssignInt2StringGeneric(asIScriptGeneric *gen) {
|
|
asINT64 *a = static_cast<asINT64 *>(gen->GetAddressOfArg(0));
|
|
QString *self = static_cast<QString *>(gen->GetObject());
|
|
*self += QString::number(*a);
|
|
gen->SetReturnAddress(self);
|
|
}
|
|
|
|
static void AddAssignUInt2StringGeneric(asIScriptGeneric *gen) {
|
|
asQWORD *a = static_cast<asQWORD *>(gen->GetAddressOfArg(0));
|
|
QString *self = static_cast<QString *>(gen->GetObject());
|
|
*self += QString::number(*a);
|
|
gen->SetReturnAddress(self);
|
|
}
|
|
|
|
static void AddAssignBool2StringGeneric(asIScriptGeneric *gen) {
|
|
bool *a = static_cast<bool *>(gen->GetAddressOfArg(0));
|
|
QString *self = static_cast<QString *>(gen->GetObject());
|
|
*self += *a ? QStringLiteral("true") : QStringLiteral("false");
|
|
gen->SetReturnAddress(self);
|
|
}
|
|
|
|
static void AddString2DoubleGeneric(asIScriptGeneric *gen) {
|
|
QString *a = static_cast<QString *>(gen->GetObject());
|
|
double *b = static_cast<double *>(gen->GetAddressOfArg(0));
|
|
auto ret_val = *a + QString::number(*b);
|
|
gen->SetReturnObject(&ret_val);
|
|
}
|
|
|
|
static void AddString2FloatGeneric(asIScriptGeneric *gen) {
|
|
QString *a = static_cast<QString *>(gen->GetObject());
|
|
float *b = static_cast<float *>(gen->GetAddressOfArg(0));
|
|
auto ret_val = *a + QString::number(*b);
|
|
gen->SetReturnObject(&ret_val);
|
|
}
|
|
|
|
static void AddString2IntGeneric(asIScriptGeneric *gen) {
|
|
QString *a = static_cast<QString *>(gen->GetObject());
|
|
asINT64 *b = static_cast<asINT64 *>(gen->GetAddressOfArg(0));
|
|
auto ret_val = *a + QString::number(*b);
|
|
gen->SetReturnObject(&ret_val);
|
|
}
|
|
|
|
static void AddString2UIntGeneric(asIScriptGeneric *gen) {
|
|
QString *a = static_cast<QString *>(gen->GetObject());
|
|
asQWORD *b = static_cast<asQWORD *>(gen->GetAddressOfArg(0));
|
|
auto ret_val = *a + QString::number(*b);
|
|
gen->SetReturnObject(&ret_val);
|
|
}
|
|
|
|
static void AddString2BoolGeneric(asIScriptGeneric *gen) {
|
|
QString *a = static_cast<QString *>(gen->GetObject());
|
|
bool *b = static_cast<bool *>(gen->GetAddressOfArg(0));
|
|
auto ret_val = *a + QString::number(*b);
|
|
gen->SetReturnObject(&ret_val);
|
|
}
|
|
|
|
static void AddDouble2StringGeneric(asIScriptGeneric *gen) {
|
|
double *a = static_cast<double *>(gen->GetAddressOfArg(0));
|
|
QString *b = static_cast<QString *>(gen->GetObject());
|
|
auto ret_val = QString::number(*a) + *b;
|
|
gen->SetReturnObject(&ret_val);
|
|
}
|
|
|
|
static void AddFloat2StringGeneric(asIScriptGeneric *gen) {
|
|
float *a = static_cast<float *>(gen->GetAddressOfArg(0));
|
|
QString *b = static_cast<QString *>(gen->GetObject());
|
|
auto ret_val = QString::number(*a) + *b;
|
|
gen->SetReturnObject(&ret_val);
|
|
}
|
|
|
|
static void AddInt2StringGeneric(asIScriptGeneric *gen) {
|
|
asINT64 *a = static_cast<asINT64 *>(gen->GetAddressOfArg(0));
|
|
QString *b = static_cast<QString *>(gen->GetObject());
|
|
auto ret_val = QString::number(*a) + *b;
|
|
gen->SetReturnObject(&ret_val);
|
|
}
|
|
|
|
static void AddUInt2StringGeneric(asIScriptGeneric *gen) {
|
|
asQWORD *a = static_cast<asQWORD *>(gen->GetAddressOfArg(0));
|
|
QString *b = static_cast<QString *>(gen->GetObject());
|
|
auto ret_val = QString::number(*a) + *b;
|
|
gen->SetReturnObject(&ret_val);
|
|
}
|
|
|
|
static void AddBool2StringGeneric(asIScriptGeneric *gen) {
|
|
bool *a = static_cast<bool *>(gen->GetAddressOfArg(0));
|
|
QString *b = static_cast<QString *>(gen->GetObject());
|
|
auto ret_val = QString::number(*a) + *b;
|
|
gen->SetReturnObject(&ret_val);
|
|
}
|
|
#endif
|
|
|
|
static void StringSubString_Generic(asIScriptGeneric *gen) {
|
|
// Get the arguments
|
|
QString *str = (QString *)gen->GetObject();
|
|
asUINT start = *(int *)gen->GetAddressOfArg(0);
|
|
int count = *(int *)gen->GetAddressOfArg(1);
|
|
|
|
// Return the substring
|
|
new (gen->GetAddressOfReturnLocation())
|
|
QString(StringSubString(start, count, *str));
|
|
}
|
|
|
|
void RegisterQString_Generic(asIScriptEngine *engine) {
|
|
int r = 0;
|
|
Q_UNUSED(r);
|
|
// QChar is wrapper of uint16 so...
|
|
r = engine->RegisterTypedef("char", "uint16");
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
|
|
// Register the string type
|
|
r = engine->RegisterObjectType("string", sizeof(QString),
|
|
asOBJ_VALUE | asOBJ_APP_CLASS_CDAK);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterStringFactory("string", GetQStringFactorySingleton());
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
|
|
// Register the object operator overloads
|
|
r = engine->RegisterObjectBehaviour(
|
|
"string", asBEHAVE_CONSTRUCT, "void f()",
|
|
asFUNCTION(ConstructStringGeneric), asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectBehaviour(
|
|
"string", asBEHAVE_CONSTRUCT, "void f(const string &in)",
|
|
asFUNCTION(CopyConstructStringGeneric), asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectBehaviour("string", asBEHAVE_DESTRUCT, "void f()",
|
|
asFUNCTION(DestructStringGeneric),
|
|
asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod(
|
|
"string", "string &opAssign(const string &in)",
|
|
asFUNCTION(AssignStringGeneric), asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod(
|
|
"string", "string &opAddAssign(const string &in)",
|
|
asFUNCTION(AddAssignStringGeneric), asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod(
|
|
"string", "bool opEquals(const string &in) const",
|
|
asFUNCTION(StringEqualsGeneric), asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod(
|
|
"string", "int opCmp(const string &in) const",
|
|
asFUNCTION(StringCmpGeneric), asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod(
|
|
"string", "string opAdd(const string &in) const",
|
|
asFUNCTION(StringAddGeneric), asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
|
|
// Register the object methods
|
|
#if AS_USE_ACCESSORS != 1
|
|
r = engine->RegisterObjectMethod("string", "uint length() const",
|
|
asFUNCTION(StringLengthGeneric),
|
|
asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
#endif
|
|
r = engine->RegisterObjectMethod("string", "void resize(uint)",
|
|
asFUNCTION(StringResizeGeneric),
|
|
asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
|
|
r = engine->RegisterObjectMethod("string", "bool isEmpty() const",
|
|
asFUNCTION(StringIsEmptyGeneric),
|
|
asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
|
|
// Register the index operator, both as a mutator and as an inspector
|
|
r = engine->RegisterObjectMethod("string", "char &opIndex(uint)",
|
|
asFUNCTION(StringCharAtGeneric),
|
|
asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod(
|
|
"string", "const char &opIndex(uint) const",
|
|
asFUNCTION(StringCharAtGeneric), asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
|
|
#if AS_NO_IMPL_OPS_WITH_STRING_AND_PRIMITIVE == 0
|
|
// Automatic conversion from values
|
|
r = engine->RegisterObjectMethod("string", "string &opAssign(double)",
|
|
asFUNCTION(AssignDouble2StringGeneric),
|
|
asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod("string", "string &opAddAssign(double)",
|
|
asFUNCTION(AddAssignDouble2StringGeneric),
|
|
asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod("string", "string opAdd(double) const",
|
|
asFUNCTION(AddString2DoubleGeneric),
|
|
asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod("string", "string opAdd_r(double) const",
|
|
asFUNCTION(AddDouble2StringGeneric),
|
|
asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
|
|
r = engine->RegisterObjectMethod("string", "string &opAssign(float)",
|
|
asFUNCTION(AssignFloat2StringGeneric),
|
|
asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod("string", "string &opAddAssign(float)",
|
|
asFUNCTION(AddAssignFloat2StringGeneric),
|
|
asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod("string", "string opAdd(float) const",
|
|
asFUNCTION(AddString2FloatGeneric),
|
|
asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod("string", "string opAdd_r(float) const",
|
|
asFUNCTION(AddFloat2StringGeneric),
|
|
asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
|
|
r = engine->RegisterObjectMethod("string", "string &opAssign(int64)",
|
|
asFUNCTION(AssignInt2StringGeneric),
|
|
asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod("string", "string &opAddAssign(int64)",
|
|
asFUNCTION(AddAssignInt2StringGeneric),
|
|
asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod("string", "string opAdd(int64) const",
|
|
asFUNCTION(AddString2IntGeneric),
|
|
asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod("string", "string opAdd_r(int64) const",
|
|
asFUNCTION(AddInt2StringGeneric),
|
|
asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
|
|
r = engine->RegisterObjectMethod("string", "string &opAssign(uint64)",
|
|
asFUNCTION(AssignUInt2StringGeneric),
|
|
asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod("string", "string &opAddAssign(uint64)",
|
|
asFUNCTION(AddAssignUInt2StringGeneric),
|
|
asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod("string", "string opAdd(uint64) const",
|
|
asFUNCTION(AddString2UIntGeneric),
|
|
asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod("string", "string opAdd_r(uint64) const",
|
|
asFUNCTION(AddUInt2StringGeneric),
|
|
asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
|
|
r = engine->RegisterObjectMethod("string", "string &opAssign(bool)",
|
|
asFUNCTION(AssignBool2StringGeneric),
|
|
asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod("string", "string &opAddAssign(bool)",
|
|
asFUNCTION(AddAssignBool2StringGeneric),
|
|
asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod("string", "string opAdd(bool) const",
|
|
asFUNCTION(AddString2BoolGeneric),
|
|
asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod("string", "string opAdd_r(bool) const",
|
|
asFUNCTION(AddBool2StringGeneric),
|
|
asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
#endif
|
|
|
|
r = engine->RegisterObjectMethod(
|
|
"string", "string substr(uint start = 0, int count = -1) const",
|
|
asFUNCTION(StringSubString_Generic), asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod(
|
|
"string", "int findFirst(const string &in, uint start = 0) const",
|
|
asFUNCTION(StringFindFirst_Generic), asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod(
|
|
"string", "int findFirstOf(const string &in, uint start = 0) const",
|
|
asFUNCTION(StringFindFirstOf_Generic), asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod(
|
|
"string", "int findLastOf(const string &in, int start = -1) const",
|
|
asFUNCTION(StringFindLastOf_Generic), asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod(
|
|
"string", "void insert(uint pos, const string &in other)",
|
|
asFUNCTION(StringInsert_Generic), asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod(
|
|
"string", "void erase(uint pos, int count = -1)",
|
|
asFUNCTION(StringErase_Generic), asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
|
|
r = engine->RegisterGlobalFunction(
|
|
"string formatInt(int64 val, const string &in options = \"\")",
|
|
asFUNCTION(formatInt_Generic), asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterGlobalFunction(
|
|
"string formatUInt(uint64 val, const string &in options = \"\")",
|
|
asFUNCTION(formatUInt_Generic), asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterGlobalFunction(
|
|
"string formatFloat(double val, const string &in options = \"\")",
|
|
asFUNCTION(formatFloat_Generic), asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterGlobalFunction("int64 parseInt(const string &in, uint "
|
|
"base = 10, bool &out ok = false)",
|
|
asFUNCTION(parseInt_Generic),
|
|
asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterGlobalFunction("uint64 parseUInt(const string &in, "
|
|
"uint base = 10, bool &out ok = false)",
|
|
asFUNCTION(parseUInt_Generic),
|
|
asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterGlobalFunction(
|
|
"double parseFloat(const string &in, bool &out ok = false)",
|
|
WRAP_FN(parseFloat_Generic), asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
|
|
r = engine->RegisterObjectMethod(
|
|
"string",
|
|
"int compare(const string &in val, bool caseSensitive = true) const",
|
|
WRAP_FN(stringCompare), asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod(
|
|
"string",
|
|
"bool contains(const string &in val, bool caseSensitive = true) const",
|
|
WRAP_FN(stringContains), asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod(
|
|
"string",
|
|
"bool endsWith(const string &in val, bool caseSensitive = true) const",
|
|
WRAP_FN(stringEndsWith), asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod("string",
|
|
"string repeated(" QSIZETYPE " times)",
|
|
WRAP_FN(stringRepeated), asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod(
|
|
"string",
|
|
"string replace(const string &in before,const string &in after, "
|
|
"bool caseSensitive = true)",
|
|
WRAP_FN(stringReplace), asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod("string", "string simplified()",
|
|
WRAP_FN(stringSimplified), asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod(
|
|
"string",
|
|
"bool startsWith(const string &in, bool caseSensitive = true)",
|
|
WRAP_FN(stringStartsWith), asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod(
|
|
"string",
|
|
"array<string>@ split(const string &in, bool skipEmpty = false, "
|
|
"bool caseSensitive = true)",
|
|
WRAP_FN(stringSplit), asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
|
|
r = engine->SetDefaultNamespace("string");
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterGlobalFunction(
|
|
"string formatInt(int64 val, const string &in options = \"\", uint "
|
|
"width = 0)",
|
|
WRAP_FN(formatInt), asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterGlobalFunction(
|
|
"string formatUInt(uint64 val, const string &in options = \"\", uint "
|
|
"width = 0)",
|
|
WRAP_FN(formatUInt), asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterGlobalFunction(
|
|
"string formatFloat(double val, const string &in options = \"\", uint "
|
|
"width = 0, uint precision = 0)",
|
|
WRAP_FN(formatFloat), asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterGlobalFunction("int64 parseInt(const string &in, uint "
|
|
"base = 10, uint &out byteCount = 0)",
|
|
WRAP_FN(parseInt), asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterGlobalFunction(
|
|
"uint64 parseUInt(const string &in, uint base = 10, uint &out "
|
|
"byteCount = 0)",
|
|
WRAP_FN(parseUInt), asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterGlobalFunction(
|
|
"double parseFloat(const string &in, uint &out byteCount = 0)",
|
|
WRAP_FN(parseFloat), asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
}
|
|
|
|
void RegisterQString(asIScriptEngine *engine) {
|
|
if (strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY"))
|
|
RegisterQString_Generic(engine);
|
|
else
|
|
RegisterQString_Native(engine);
|
|
}
|
|
|
|
// 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:
|
|
//
|
|
// array<string> array = {"A", "B", "", "D"};
|
|
// string str = join(array, "|");
|
|
//
|
|
// The resulting string is:
|
|
//
|
|
// "A|B||D"
|
|
//
|
|
// AngelScript signature:
|
|
// string join(const array<string> &in array, const string &in delim)
|
|
static QString StringJoin(const CScriptArray &array, const QString &delim) {
|
|
// Create the new string
|
|
QString str;
|
|
if (array.GetSize()) {
|
|
int n;
|
|
for (n = 0; n < (int)array.GetSize() - 1; n++) {
|
|
str += *(const QString *)array.At(n);
|
|
str += delim;
|
|
}
|
|
|
|
// Add the last part
|
|
str += *(const QString *)array.At(n);
|
|
}
|
|
|
|
return str;
|
|
}
|
|
|
|
static void StringJoin_Generic(asIScriptGeneric *gen) {
|
|
// Get the arguments
|
|
CScriptArray *array = *(CScriptArray **)gen->GetAddressOfArg(0);
|
|
QString *delim = *(QString **)gen->GetAddressOfArg(1);
|
|
|
|
// Return the string
|
|
new (gen->GetAddressOfReturnLocation()) QString(StringJoin(*array, *delim));
|
|
}
|
|
|
|
static int StringCompare(const QString &s1, const QString &s2,
|
|
bool caseSensitive) {
|
|
return QString::compare(
|
|
s1, s2, caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive);
|
|
}
|
|
|
|
// This is where the utility functions are registered.
|
|
// The string type must have been registered first.
|
|
void RegisterQStringUtils(asIScriptEngine *engine) {
|
|
int r = engine->SetDefaultNamespace("string");
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
|
|
if (strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY")) {
|
|
r = engine->RegisterGlobalFunction(
|
|
"string join(const array<string> &in, const string &in)",
|
|
asFUNCTION(StringJoin_Generic), asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
|
|
r = engine->RegisterGlobalFunction(
|
|
"int compare(const string &in, const string &in, bool = true)",
|
|
WRAP_FN(StringCompare), asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
} else {
|
|
r = engine->RegisterGlobalFunction(
|
|
"string join(const array<string> &in, const string &in)",
|
|
asFUNCTION(StringJoin), asCALL_CDECL);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
|
|
r = engine->RegisterGlobalFunction(
|
|
"int compare(const string &in, const string &in, bool = true)",
|
|
asFUNCTION(StringCompare), asCALL_CDECL);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
}
|
|
engine->SetDefaultNamespace("");
|
|
}
|
|
|
|
// 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 string::findFirst(const regex::exp &in exp, uint start = 0) const
|
|
static int StringFindFirstReg(const QRegularExpression &exp, asUINT start,
|
|
const QString &str) {
|
|
// We don't register the method directly because the argument types change
|
|
// between 32bit and 64bit platforms
|
|
return (int)str.indexOf(exp, start);
|
|
}
|
|
|
|
// This function returns the index of the first position where the one of the
|
|
// bytes in substring exists in the input string. If the characters in the
|
|
// substring doesn't exist in the input string -1 is returned.
|
|
//
|
|
// AngelScript signature:
|
|
// int string::findFirstOf(const regex::exp &in exp, uint start = 0) const
|
|
static int StringFindFirstOfReg(const QRegularExpression &exp, asUINT start,
|
|
const QString &str) {
|
|
// We don't register the method directly because the argument types change
|
|
// between 32bit and 64bit platforms
|
|
return (int)str.indexOf(exp, start);
|
|
}
|
|
|
|
// This function returns the index of the last position where the one of the
|
|
// bytes in substring exists in the input string. If the characters in the
|
|
// substring doesn't exist in the input string -1 is returned.
|
|
//
|
|
// AngelScript signature:
|
|
// int string::findLastOf(const regex::exp &in exp, uint start = -1) const
|
|
static int StringFindLastOfReg(const QRegularExpression &exp, asUINT start,
|
|
const QString &str) {
|
|
// We don't register the method directly because the argument types change
|
|
// between 32bit and 64bit platforms
|
|
return (int)str.lastIndexOf(exp, start);
|
|
}
|
|
|
|
// bool contains(const regex::exp &in exp) const
|
|
static bool stringContainsReg(const QRegularExpression &exp,
|
|
const QString &str) {
|
|
return str.contains(exp);
|
|
}
|
|
|
|
// array<string>@ split(const regex::exp &exp, bool skipEmpty = false)
|
|
static CScriptArray *stringSplitReg(const QRegularExpression &exp,
|
|
bool skipEmpty, const QString &str) {
|
|
return retarrayWrapperFunction(
|
|
[&]() -> QStringList {
|
|
return str.split(exp, skipEmpty ? Qt::SkipEmptyParts
|
|
: Qt::KeepEmptyParts);
|
|
},
|
|
"array<string>");
|
|
}
|
|
|
|
void RegisterQStringRegExSupport(asIScriptEngine *engine) {
|
|
Q_ASSERT(engine->GetTypeInfoByName("regex::exp"));
|
|
|
|
int r = engine->SetDefaultNamespace("string");
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
|
|
if (strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY")) {
|
|
r = engine->RegisterObjectMethod(
|
|
"string",
|
|
"int findFirst(const regex::exp &in, uint start = 0) const",
|
|
WRAP_FN(StringFindFirstReg), asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod(
|
|
"string",
|
|
"int findFirstOf(const regex::exp &in, uint start = 0) const",
|
|
WRAP_FN(StringFindFirstOfReg), asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod(
|
|
"string",
|
|
"int findLastOf(const regex::exp &in, int start = -1) const",
|
|
WRAP_FN(StringFindLastOfReg), asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod(
|
|
"string", "bool contains(const regex::exp &in) const",
|
|
WRAP_FN(stringContainsReg), asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod(
|
|
"string",
|
|
"array<string>@ split(const regex::exp &in, "
|
|
"bool skipEmpty = false)",
|
|
WRAP_FN(stringSplitReg), asCALL_GENERIC);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
|
|
} else {
|
|
r = engine->RegisterObjectMethod(
|
|
"string",
|
|
"int findFirst(const regex::exp &in, uint start = 0) const",
|
|
asFUNCTION(StringFindFirstReg), asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod(
|
|
"string",
|
|
"int findFirstOf(const regex::exp &in, uint start = 0) const",
|
|
asFUNCTION(StringFindFirstOfReg), asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod(
|
|
"string",
|
|
"int findLastOf(const regex::exp &in, int start = -1) const",
|
|
asFUNCTION(StringFindLastOfReg), asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod(
|
|
"string", "bool contains(const regex::exp &in) const",
|
|
asFUNCTION(stringContainsReg), asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
r = engine->RegisterObjectMethod(
|
|
"string",
|
|
"array<string>@ split(const regex::exp &in, "
|
|
"bool skipEmpty = false)",
|
|
asFUNCTION(stringSplitReg), asCALL_CDECL_OBJLAST);
|
|
Q_ASSERT(r >= 0);
|
|
Q_UNUSED(r);
|
|
}
|
|
engine->SetDefaultNamespace("");
|
|
}
|
|
|
|
END_AS_NAMESPACE
|