start cleaning up ConsoleValueRef's

This commit is contained in:
Jeff Hutchinson 2021-03-30 23:58:07 -04:00
parent 35500a87c6
commit 5e81c021f5
8 changed files with 331 additions and 233 deletions

View file

@ -28,7 +28,6 @@
class Stream; class Stream;
class ConsoleValue; class ConsoleValue;
class ConsoleValueRef;
/// Core TorqueScript code management class. /// Core TorqueScript code management class.
/// ///
@ -130,7 +129,7 @@ public:
/// with, zero being the top of the stack. If the the index is /// with, zero being the top of the stack. If the the index is
/// -1 a new frame is created. If the index is out of range the /// -1 a new frame is created. If the index is out of range the
/// top stack frame is used. /// top stack frame is used.
ConsoleValueRef compileExec(StringTableEntry fileName, const char *script, ConsoleValue compileExec(StringTableEntry fileName, const char *script,
bool noCalls, S32 setFrame = -1); bool noCalls, S32 setFrame = -1);
/// Executes the existing code in the CodeBlock. The return string is any /// Executes the existing code in the CodeBlock. The return string is any
@ -148,9 +147,9 @@ public:
/// -1 a new frame is created. If the index is out of range the /// -1 a new frame is created. If the index is out of range the
/// top stack frame is used. /// top stack frame is used.
/// @param packageName The code package name or null. /// @param packageName The code package name or null.
ConsoleValueRef exec(U32 offset, const char *fnName, Namespace *ns, U32 argc, ConsoleValue exec(U32 offset, const char *fnName, Namespace *ns, U32 argc,
ConsoleValueRef *argv, bool noCalls, StringTableEntry packageName, ConsoleValue *argv, bool noCalls, StringTableEntry packageName,
S32 setFrame = -1); S32 setFrame = -1);
}; };
#endif #endif

View file

@ -41,9 +41,37 @@
#include "platform/threads/mutex.h" #include "platform/threads/mutex.h"
#include "core/util/journal/journal.h" #include "core/util/journal/journal.h"
#include "cinterface/cinterface.h" #include "cinterface/cinterface.h"
#include "console/consoleValueStack.h"
extern StringStack STR; extern StringStack STR;
extern ConsoleValueStack CSTK; extern ConsoleValueStack<4096> gCallStack;
S32 ConsoleValue::sBufferOffset = 0;
char ConsoleValue::sConversionBuffer[ConversionBufferSize];
void ConsoleValue::init()
{
sBufferOffset = 0;
dMemset(sConversionBuffer, '\0', ConversionBufferSize);
}
char* ConsoleValue::convertToBuffer() const
{
sBufferOffset += StringSize;
if (sBufferOffset > ConversionBufferSize)
{
dMemset(sConversionBuffer, '\0', ConversionBufferSize);
sBufferOffset = 0;
}
char* offset = sConversionBuffer + sBufferOffset;
if (type == ConsoleValueType::cvFloat)
dSprintf(offset, StringSize, "%.9g", f);
else
dSprintf(offset, StringSize, "%lld", i);
return offset;
}
ConsoleDocFragment* ConsoleDocFragment::smFirst; ConsoleDocFragment* ConsoleDocFragment::smFirst;
ExprEvalState gEvalState; ExprEvalState gEvalState;
@ -1469,7 +1497,7 @@ bool executeFile(const char* fileName, bool noCalls, bool journalScript)
return ret; return ret;
} }
ConsoleValueRef evaluate(const char* string, bool echo, const char *fileName) ConsoleValue evaluate(const char* string, bool echo, const char *fileName)
{ {
ConsoleStackFrameSaver stackSaver; ConsoleStackFrameSaver stackSaver;
stackSaver.save(); stackSaver.save();
@ -1486,11 +1514,11 @@ ConsoleValueRef evaluate(const char* string, bool echo, const char *fileName)
fileName = StringTable->insert(fileName); fileName = StringTable->insert(fileName);
CodeBlock *newCodeBlock = new CodeBlock(); CodeBlock *newCodeBlock = new CodeBlock();
return newCodeBlock->compileExec(fileName, string, false, fileName ? -1 : 0); return std::move(newCodeBlock->compileExec(fileName, string, false, fileName ? -1 : 0));
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
ConsoleValueRef evaluatef(const char* string, ...) ConsoleValue evaluatef(const char* string, ...)
{ {
ConsoleStackFrameSaver stackSaver; ConsoleStackFrameSaver stackSaver;
stackSaver.save(); stackSaver.save();
@ -1507,36 +1535,41 @@ ConsoleValueRef evaluatef(const char* string, ...)
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Internal execute for global function which does not save the stack // Internal execute for global function which does not save the stack
ConsoleValueRef _internalExecute(S32 argc, ConsoleValueRef argv[]) ConsoleValue _internalExecute(S32 argc, ConsoleValue argv[])
{ {
StringTableEntry funcName = StringTable->insert(argv[0].getString());
const char** argv_str = static_cast<const char**>(malloc((argc - 1) * sizeof(char *))); const char** argv_str = static_cast<const char**>(malloc((argc - 1) * sizeof(char *)));
for (int i = 0; i < argc - 1; i++) for (int i = 0; i < argc - 1; i++)
{ {
argv_str[i] = argv[i + 1]; argv_str[i] = argv[i + 1].getString();
} }
bool result; bool result;
const char* methodRes = CInterface::CallFunction(NULL, argv[0], argv_str, argc - 1, &result); const char* methodRes = CInterface::CallFunction(NULL, funcName, argv_str, argc - 1, &result);
free(argv_str); free(argv_str);
if (result) if (result)
{ {
return ConsoleValueRef::fromValue(CSTK.pushString(methodRes)); ConsoleValue ret;
ret.setString(methodRes, dStrlen(methodRes));
return std::move(ret);
} }
Namespace::Entry *ent; Namespace::Entry *ent;
StringTableEntry funcName = StringTable->insert(argv[0]);
ent = Namespace::global()->lookup(funcName); ent = Namespace::global()->lookup(funcName);
if(!ent) if(!ent)
{ {
warnf(ConsoleLogEntry::Script, "%s: Unknown command.", (const char*)argv[0]); warnf(ConsoleLogEntry::Script, "%s: Unknown command.", funcName);
STR.clearFunctionOffset(); STR.clearFunctionOffset();
return ConsoleValueRef(); return std::move(ConsoleValue());
} }
return ent->execute(argc, argv, &gEvalState);
return std::move(ent->execute(argc, argv, &gEvalState));
} }
ConsoleValueRef execute(S32 argc, ConsoleValueRef argv[]) ConsoleValue execute(S32 argc, ConsoleValue argv[])
{ {
#ifdef TORQUE_MULTITHREAD #ifdef TORQUE_MULTITHREAD
if(isMainThread()) if(isMainThread())
@ -1558,23 +1591,23 @@ ConsoleValueRef execute(S32 argc, ConsoleValueRef argv[])
#endif #endif
} }
ConsoleValueRef execute(S32 argc, const char *argv[]) ConsoleValue execute(S32 argc, const char *argv[])
{ {
ConsoleStackFrameSaver stackSaver; ConsoleStackFrameSaver stackSaver;
stackSaver.save(); stackSaver.save();
StringStackConsoleWrapper args(argc, argv); StringArrayToConsoleValueWrapper args(argc, argv);
return execute(args.count(), args); return std::move(execute(args.count(), args));
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Internal execute for object method which does not save the stack // Internal execute for object method which does not save the stack
ConsoleValueRef _internalExecute(SimObject *object, S32 argc, ConsoleValueRef argv[], bool thisCallOnly) static ConsoleValue _internalExecute(SimObject *object, S32 argc, ConsoleValue argv[], bool thisCallOnly)
{ {
if(argc < 2) if(argc < 2)
{ {
STR.clearFunctionOffset(); STR.clearFunctionOffset();
return ConsoleValueRef(); return std::move(ConsoleValue());
} }
// [neo, 10/05/2007 - #3010] // [neo, 10/05/2007 - #3010]
@ -1591,65 +1624,65 @@ ConsoleValueRef _internalExecute(SimObject *object, S32 argc, ConsoleValueRef ar
} }
} }
StringTableEntry funcName = StringTable->insert(argv[0].getString());
const char** argv_str = static_cast<const char**>(malloc((argc - 2) * sizeof(char *))); const char** argv_str = static_cast<const char**>(malloc((argc - 2) * sizeof(char *)));
for (int i = 0; i < argc - 2; i++) for (int i = 0; i < argc - 2; i++)
{ {
argv_str[i] = argv[i + 2]; argv_str[i] = argv[i + 2].getString();
} }
bool result; bool result;
const char* methodRes = CInterface::CallMethod(object, argv[0], argv_str, argc - 2, &result); const char* methodRes = CInterface::CallMethod(object, funcName, argv_str, argc - 2, &result);
free(argv_str); free(argv_str);
if (result) if (result)
{ {
return ConsoleValueRef::fromValue(CSTK.pushString(methodRes)); ConsoleValue val;
val.setString(methodRes, dStrlen(methodRes));
return std::move(val);
} }
if(object->getNamespace()) if(object->getNamespace())
{ {
U32 ident = object->getId(); U32 ident = object->getId();
ConsoleValueRef oldIdent(argv[1]); const char* oldIdent = argv[1].getString();
StringTableEntry funcName = StringTable->insert(argv[0]);
Namespace::Entry *ent = object->getNamespace()->lookup(funcName); Namespace::Entry *ent = object->getNamespace()->lookup(funcName);
if(ent == NULL) if(ent == NULL)
{ {
//warnf(ConsoleLogEntry::Script, "%s: undefined for object '%s' - id %d", funcName, object->getName(), object->getId()); warnf(ConsoleLogEntry::Script, "%s: undefined for object '%s' - id %d", funcName, object->getName(), object->getId());
STR.clearFunctionOffset(); STR.clearFunctionOffset();
return ConsoleValueRef(); return std::move(ConsoleValue());
} }
// Twiddle %this argument // Twiddle %this argument
ConsoleValue func_ident; argv[1].setInt(ident);
func_ident.setIntValue((S32)ident);
argv[1] = ConsoleValueRef::fromValue(&func_ident);
SimObject *save = gEvalState.thisObject; SimObject *save = gEvalState.thisObject;
gEvalState.thisObject = object; gEvalState.thisObject = object;
ConsoleValueRef ret = ent->execute(argc, argv, &gEvalState); ConsoleValue ret = std::move(ent->execute(argc, argv, &gEvalState));
gEvalState.thisObject = save; gEvalState.thisObject = save;
// Twiddle it back // Twiddle it back
argv[1] = oldIdent; argv[1].setString(oldIdent, dStrlen(oldIdent));
return ret; return std::move(ret);
} }
warnf(ConsoleLogEntry::Script, "Con::execute - %d has no namespace: %s", object->getId(), (const char*)argv[0]); warnf(ConsoleLogEntry::Script, "Con::execute - %d has no namespace: %s", object->getId(), funcName);
STR.clearFunctionOffset(); STR.clearFunctionOffset();
return ConsoleValueRef(); return std::move(ConsoleValue());
} }
ConsoleValue execute(SimObject *object, S32 argc, ConsoleValue argv[], bool thisCallOnly)
ConsoleValueRef execute(SimObject *object, S32 argc, ConsoleValueRef argv[], bool thisCallOnly)
{ {
if(argc < 2) if(argc < 2)
{ {
STR.clearFunctionOffset(); STR.clearFunctionOffset();
return ConsoleValueRef(); return std::move(ConsoleValue());
} }
ConsoleStackFrameSaver stackSaver; ConsoleStackFrameSaver stackSaver;
@ -1659,7 +1692,7 @@ ConsoleValueRef execute(SimObject *object, S32 argc, ConsoleValueRef argv[], boo
{ {
if (isMainThread()) if (isMainThread())
{ {
return _internalExecute(object, argc, argv, thisCallOnly); return std::move(_internalExecute(object, argc, argv, thisCallOnly));
} }
else else
{ {
@ -1669,34 +1702,34 @@ ConsoleValueRef execute(SimObject *object, S32 argc, ConsoleValueRef argv[], boo
} }
} }
warnf(ConsoleLogEntry::Script, "Con::execute - %d has no namespace: %s", object->getId(), (const char*)argv[0]); warnf(ConsoleLogEntry::Script, "Con::execute - %d has no namespace: %s", object->getId(), argv[0].getString());
STR.clearFunctionOffset(); STR.clearFunctionOffset();
return ConsoleValueRef(); return std::move(ConsoleValue());
} }
ConsoleValueRef execute(SimObject *object, S32 argc, const char *argv[], bool thisCallOnly) ConsoleValue execute(SimObject *object, S32 argc, const char *argv[], bool thisCallOnly)
{ {
ConsoleStackFrameSaver stackSaver; ConsoleStackFrameSaver stackSaver;
stackSaver.save(); stackSaver.save();
StringStackConsoleWrapper args(argc, argv); StringArrayToConsoleValueWrapper args(argc, argv);
return execute(object, args.count(), args, thisCallOnly); return std::move(execute(object, args.count(), args, thisCallOnly));
} }
inline ConsoleValueRef _executef(SimObject *obj, S32 checkArgc, S32 argc, ConsoleValueRef *argv) inline ConsoleValue _executef(SimObject *obj, S32 checkArgc, S32 argc, ConsoleValue *argv)
{ {
const U32 maxArg = 12; const U32 maxArg = 12;
AssertWarn(checkArgc == argc, "Incorrect arg count passed to Con::executef(SimObject*)"); AssertFatal(checkArgc == argc, "Incorrect arg count passed to Con::executef(SimObject*)");
AssertFatal(argc <= maxArg - 1, "Too many args passed to Con::_executef(SimObject*). Please update the function to handle more."); AssertFatal(argc <= maxArg - 1, "Too many args passed to Con::_executef(SimObject*). Please update the function to handle more.");
return execute(obj, argc, argv); return std::move(execute(obj, argc, argv));
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
inline ConsoleValueRef _executef(S32 checkArgc, S32 argc, ConsoleValueRef *argv) inline ConsoleValue _executef(S32 checkArgc, S32 argc, ConsoleValue *argv)
{ {
const U32 maxArg = 10; const U32 maxArg = 10;
AssertFatal(checkArgc == argc, "Incorrect arg count passed to Con::executef()"); AssertFatal(checkArgc == argc, "Incorrect arg count passed to Con::executef()");
AssertFatal(argc <= maxArg, "Too many args passed to Con::_executef(). Please update the function to handle more."); AssertFatal(argc <= maxArg, "Too many args passed to Con::_executef(). Please update the function to handle more.");
return execute(argc, argv); return std::move(execute(argc, argv));
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -1893,16 +1926,11 @@ StringTableEntry getModNameFromPath(const char *path)
void postConsoleInput( RawData data ) void postConsoleInput( RawData data )
{ {
// TODO(JTH): Mem leak
// Schedule this to happen at the next time event. // Schedule this to happen at the next time event.
ConsoleValue values[2]; ConsoleValue* argv = new ConsoleValue[2];
ConsoleValueRef argv[2]; argv[0].setString("eval", 4);
argv[1].setString(reinterpret_cast<const char*>(data.data), dStrlen(reinterpret_cast<const char*>(data.data)));
values[0].init();
values[0].setStringValue("eval");
values[1].init();
values[1].setStringValue((const char*)data.data);
argv[0].value = &values[0];
argv[1].value = &values[1];
Sim::postCurrentEvent(Sim::getRootGroup(), new SimConsoleEvent(2, argv, false)); Sim::postCurrentEvent(Sim::getRootGroup(), new SimConsoleEvent(2, argv, false));
} }
@ -2555,27 +2583,29 @@ StringArrayToConsoleValueWrapper::~StringArrayToConsoleValueWrapper()
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
ConsoleValueRef _BaseEngineConsoleCallbackHelper::_exec() ConsoleValue _BaseEngineConsoleCallbackHelper::_exec()
{ {
ConsoleValueRef returnValue;
if( mThis ) if( mThis )
{ {
// Cannot invoke callback until object has been registered // Cannot invoke callback until object has been registered
if (mThis->isProperlyAdded()) { if (mThis->isProperlyAdded())
returnValue = Con::_internalExecute( mThis, mArgc, mArgv, false ); {
} else { ConsoleValue returnValue = std::move(Con::_internalExecute( mThis, mArgc, mArgv, false ));
STR.clearFunctionOffset(); mArgc = mInitialArgc; // reset
returnValue = ConsoleValueRef(); return returnValue;
} }
}
else
returnValue = Con::_internalExecute( mArgc, mArgv );
STR.clearFunctionOffset();
mArgc = mInitialArgc; // reset
return std::move(ConsoleValue());
}
ConsoleValue returnValue = std::move(Con::_internalExecute( mArgc, mArgv ));
mArgc = mInitialArgc; // reset args mArgc = mInitialArgc; // reset args
return returnValue; return std::move(returnValue);
} }
ConsoleValueRef _BaseEngineConsoleCallbackHelper::_execLater(SimConsoleThreadExecEvent *evt) ConsoleValue _BaseEngineConsoleCallbackHelper::_execLater(SimConsoleThreadExecEvent *evt)
{ {
mArgc = mInitialArgc; // reset args mArgc = mInitialArgc; // reset args
Sim::postEvent((SimObject*)Sim::getRootGroup(), evt, Sim::getCurrentTime()); Sim::postEvent((SimObject*)Sim::getRootGroup(), evt, Sim::getCurrentTime());
@ -2586,7 +2616,7 @@ ConsoleValueRef _BaseEngineConsoleCallbackHelper::_execLater(SimConsoleThreadExe
void ConsoleStackFrameSaver::save() void ConsoleStackFrameSaver::save()
{ {
CSTK.pushFrame(); gCallStack.pushFrame(0);
STR.pushFrame(); STR.pushFrame();
mSaved = true; mSaved = true;
} }
@ -2595,7 +2625,7 @@ void ConsoleStackFrameSaver::restore()
{ {
if (mSaved) if (mSaved)
{ {
CSTK.popFrame(); gCallStack.popFrame();
STR.popFrame(); STR.popFrame();
} }
} }

View file

@ -117,188 +117,250 @@ struct ConsoleLogEntry
typedef const char *StringTableEntry; typedef const char *StringTableEntry;
extern char *typeValueEmpty; extern char *typeValueEmpty;
enum ConsoleValueType
{
cvNone = -5,
cvInteger = -4,
cvFloat = -3,
cvString = -2,
cvSTEntry = -1,
cvConsoleValueType = 0
};
struct ConsoleValueConsoleType
{
void* dataPtr;
EnumTable* enumTable;
};
// TODO: replace malloc/free with custom allocator...
class ConsoleValue class ConsoleValue
{ {
public: union
enum
{ {
TypeInternalInt = -5, F64 f;
TypeInternalFloat = -4, S64 i;
TypeInternalStringStackPtr = -3, char* s;
TypeInternalStackString = -2, void* data;
TypeInternalString = -1, ConsoleValueConsoleType* ct;
}; };
S32 type; S32 type;
public: enum Constants
// NOTE: This is protected to ensure no one outside
// of this structure is messing with it.
#pragma warning( push )
#pragma warning( disable : 4201 ) // warning C4201: nonstandard extension used : nameless struct/union
// An variable is either a real dynamic type or
// its one exposed from C++ using a data pointer.
//
// We use this nameless union and struct setup
// to optimize the memory usage.
union
{ {
struct ConversionBufferSize = 1024,
{ StringSize = 16
char *sval;
U32 ival; // doubles as strlen when type is TypeInternalString
F32 fval;
U32 bufferLen;
};
struct
{
/// The real data pointer.
void *dataPtr;
/// The enum lookup table for enumerated types.
const EnumTable *enumTable;
};
}; };
U32 getIntValue(); static char sConversionBuffer[ConversionBufferSize];
S32 getSignedIntValue(); static S32 sBufferOffset;
F32 getFloatValue();
const char *getStringValue();
StringStackPtr getStringStackPtr();
bool getBoolValue();
void setIntValue(U32 val); char* convertToBuffer() const;
void setIntValue(S32 val);
void setFloatValue(F32 val);
void setStringValue(const char *value);
void setStackStringValue(const char *value);
void setStringStackPtrValue(StringStackPtr ptr);
void setBoolValue(bool val);
void init() TORQUE_FORCEINLINE bool isStringType() const
{ {
ival = 0; return type == ConsoleValueType::cvString || type == ConsoleValueType::cvSTEntry;
fval = 0;
sval = typeValueEmpty;
bufferLen = 0;
type = TypeInternalString;
} }
void cleanup() TORQUE_FORCEINLINE bool isNumberType() const
{ {
if ((type <= TypeInternalString) && (bufferLen > 0)) return type == ConsoleValueType::cvFloat || type == ConsoleValueType::cvInteger;
}
TORQUE_FORCEINLINE bool hasAllocatedData() const
{
return type == ConsoleValueType::cvString || type >= ConsoleValueType::cvConsoleValueType;
}
TORQUE_FORCEINLINE const char* getConsoleData() const
{
return Con::getData(type, ct->dataPtr, 0, ct->enumTable);
}
TORQUE_FORCEINLINE void cleanupData()
{
if (hasAllocatedData())
{ {
dFree(sval); dFree(data);
bufferLen = 0;
} }
sval = typeValueEmpty;
type = ConsoleValue::TypeInternalString;
ival = 0;
fval = 0;
} }
ConsoleValue() { init(); };
~ConsoleValue() { cleanup(); };
};
// Proxy class for console variables
// Can point to existing console variables,
// or act like a free floating value.
class ConsoleValueRef
{
public: public:
ConsoleValue *value; ConsoleValue()
{
type = ConsoleValueType::cvNone;
}
ConsoleValueRef() : value(0) { ; } ConsoleValue(ConsoleValue&& ref)
~ConsoleValueRef() { ; } {
cleanupData();
type = ref.type;
ConsoleValueRef(const ConsoleValueRef &ref); switch (ref.type)
{
TORQUE_UNLIKELY
case cvNone:
break;
case cvInteger:
i = ref.i;
break;
case cvFloat:
f = ref.f;
break;
case cvSTEntry:
TORQUE_CASE_FALLTHROUGH
case cvString:
s = ref.s;
break;
default:
data = ref.data;
break;
}
static ConsoleValueRef fromValue(ConsoleValue *value) { ConsoleValueRef ref; ref.value = value; return ref; } ref.type = cvNone;
}
const char *getStringValue() { return value ? value->getStringValue() : ""; } ConsoleValue(const ConsoleValue&) = delete;
StringStackPtr getStringStackPtrValue() { return value ? value->getStringStackPtr() : 0; } ConsoleValue& operator=(const ConsoleValue&) = delete;
inline U32 getIntValue() { return value ? value->getIntValue() : 0; } TORQUE_FORCEINLINE ~ConsoleValue()
inline S32 getSignedIntValue() { return value ? value->getSignedIntValue() : 0; } {
inline F32 getFloatValue() { return value ? value->getFloatValue() : 0.0f; } cleanupData();
inline bool getBoolValue() { return value ? value->getBoolValue() : false; } }
inline operator const char*() { return getStringValue(); } TORQUE_FORCEINLINE F64 getFloat() const
inline operator String() { return String(getStringValue()); } {
inline operator U32() { return getIntValue(); } AssertFatal(type == ConsoleValueType::cvNone, "Attempted to access ConsoleValue when it has no value!");
inline operator S32() { return getSignedIntValue(); } if (type == ConsoleValueType::cvFloat)
inline operator F32() { return getFloatValue(); } return f;
inline operator bool() { return getBoolValue(); } if (type == ConsoleValueType::cvInteger)
return i;
if (isStringType())
return dAtof(s);
return dAtof(getConsoleData());
}
inline bool isStringStackPtr() { return value ? value->type == ConsoleValue::TypeInternalStringStackPtr : false; } TORQUE_FORCEINLINE S64 getInt() const
inline bool isString() { return value ? value->type >= ConsoleValue::TypeInternalStringStackPtr : true; } {
inline bool isInt() { return value ? value->type == ConsoleValue::TypeInternalInt : false; } AssertFatal(type == ConsoleValueType::cvNone, "Attempted to access ConsoleValue when it has no value!");
inline bool isFloat() { return value ? value->type == ConsoleValue::TypeInternalFloat : false; } if (type == ConsoleValueType::cvInteger)
inline S32 getType() { return value ? value->type : -1; } return i;
if (type == ConsoleValueType::cvFloat)
return f;
if (isStringType())
return dAtoi(s);
return dAtoi(getConsoleData());
}
// Note: operators replace value TORQUE_FORCEINLINE const char* getString() const
ConsoleValueRef& operator=(const ConsoleValueRef &other); {
ConsoleValueRef& operator=(const char *newValue); AssertFatal(type == ConsoleValueType::cvNone, "Attempted to access ConsoleValue when it has no value!");
ConsoleValueRef& operator=(U32 newValue); if (isStringType())
ConsoleValueRef& operator=(S32 newValue); return s;
ConsoleValueRef& operator=(F32 newValue); if (isNumberType())
ConsoleValueRef& operator=(F64 newValue); return convertToBuffer();
return getConsoleData();
}
TORQUE_FORCEINLINE bool getBool() const
{
AssertFatal(type == ConsoleValueType::cvNone, "Attempted to access ConsoleValue when it has no value!");
if (type == ConsoleValueType::cvInteger)
return (bool)i;
if (type == ConsoleValueType::cvFloat)
return (bool)f;
if (isStringType())
return dAtob(s);
return dAtob(getConsoleData());
}
TORQUE_FORCEINLINE void setFloat(const F64 val)
{
AssertFatal(type == ConsoleValueType::cvNone, "Attempted to access ConsoleValue when it has no value!");
cleanupData();
type = ConsoleValueType::cvFloat;
f = val;
}
TORQUE_FORCEINLINE void setInt(const S64 val)
{
cleanupData();
type = ConsoleValueType::cvInteger;
i = val;
}
TORQUE_FORCEINLINE void setString(const char* val, S32 len)
{
cleanupData();
type = ConsoleValueType::cvString;
s = (char*)dMalloc(len + 1);
s[len] = 0x0;
dStrcpy(s, val, len);
}
TORQUE_FORCEINLINE void setBool(const bool val)
{
cleanupData();
type = ConsoleValueType::cvInteger;
i = (int)val;
}
TORQUE_FORCEINLINE void setStringTableEntry(StringTableEntry val)
{
cleanupData();
type = ConsoleValueType::cvSTEntry;
s = const_cast<char*>(val);
}
TORQUE_FORCEINLINE void setConsoleData(S32 consoleType, void* dataPtr, EnumTable* enumTable)
{
cleanupData();
type = ConsoleValueType::cvSTEntry;
ct = new ConsoleValueConsoleType{ dataPtr, enumTable };
}
TORQUE_FORCEINLINE S32 getType() const
{
return type;
}
static void init();
static S32 getConstantBufferCount() { return (S32)ConversionBufferSize / StringSize; }
}; };
// Overrides to allow ConsoleValueRefs to be directly converted to S32&F32
inline S32 dAtoi(ConsoleValueRef &ref)
{
return ref.getSignedIntValue();
}
inline F32 dAtof(ConsoleValueRef &ref)
{
return ref.getFloatValue();
}
inline bool dAtob(ConsoleValue &ref)
{
return ref.getBoolValue();
}
// Transparently converts ConsoleValue[] to const char** // Transparently converts ConsoleValue[] to const char**
class StringStackWrapper class ConsoleValueToStringArrayWrapper
{ {
public: public:
const char **argv; const char **argv;
int argc; S32 argc;
StringStackWrapper(int targc, ConsoleValueRef targv[]); ConsoleValueToStringArrayWrapper(int targc, ConsoleValue* targv);
~StringStackWrapper(); ~ConsoleValueToStringArrayWrapper();
const char* operator[](int idx) { return argv[idx]; } const char* operator[](S32 idx) { return argv[idx]; }
operator const char**() { return argv; } operator const char**() { return argv; }
int count() { return argc; } S32 count() { return argc; }
}; };
// Transparently converts const char** to ConsoleValue // Transparently converts const char** to ConsoleValue
class StringStackConsoleWrapper class StringArrayToConsoleValueWrapper
{ {
public: public:
ConsoleValue *argvValue; ConsoleValue *argv;
ConsoleValueRef *argv; S32 argc;
int argc;
StringStackConsoleWrapper(int targc, const char **targv); StringArrayToConsoleValueWrapper(int targc, const char **targv);
~StringStackConsoleWrapper(); ~StringArrayToConsoleValueWrapper();
ConsoleValueRef& operator[](int idx) { return argv[idx]; } ConsoleValue& operator[](int idx) { return argv[idx]; }
operator ConsoleValueRef*() { return argv; } operator ConsoleValue*() { return argv; }
int count() { return argc; } S32 count() { return argc; }
}; };
/// @defgroup console_callbacks Scripting Engine Callbacks /// @defgroup console_callbacks Scripting Engine Callbacks
@ -319,11 +381,11 @@ public:
/// @{ /// @{
/// ///
typedef const char * (*StringCallback)(SimObject *obj, S32 argc, ConsoleValueRef argv[]); typedef const char * (*StringCallback)(SimObject *obj, S32 argc, ConsoleValue argv[]);
typedef S32(*IntCallback)(SimObject *obj, S32 argc, ConsoleValueRef argv[]); typedef S32(*IntCallback)(SimObject *obj, S32 argc, ConsoleValue argv[]);
typedef F32(*FloatCallback)(SimObject *obj, S32 argc, ConsoleValueRef argv[]); typedef F32(*FloatCallback)(SimObject *obj, S32 argc, ConsoleValue argv[]);
typedef void(*VoidCallback)(SimObject *obj, S32 argc, ConsoleValueRef argv[]); // We have it return a value so things don't break.. typedef void(*VoidCallback)(SimObject *obj, S32 argc, ConsoleValue argv[]); // We have it return a value so things don't break..
typedef bool(*BoolCallback)(SimObject *obj, S32 argc, ConsoleValueRef argv[]); typedef bool(*BoolCallback)(SimObject *obj, S32 argc, ConsoleValue argv[]);
typedef void(*ConsumerCallback)(U32 level, const char *consoleLine); typedef void(*ConsumerCallback)(U32 level, const char *consoleLine);
/// @} /// @}
@ -786,8 +848,8 @@ namespace Con
/// char* result = execute(2, argv); /// char* result = execute(2, argv);
/// @endcode /// @endcode
/// NOTE: this function restores the console stack on return. /// NOTE: this function restores the console stack on return.
ConsoleValueRef execute(S32 argc, const char* argv[]); ConsoleValue execute(S32 argc, const char* argv[]);
ConsoleValueRef execute(S32 argc, ConsoleValueRef argv[]); ConsoleValue execute(S32 argc, ConsoleValue argv[]);
/// Call a Torque Script member function of a SimObject from C/C++ code. /// Call a Torque Script member function of a SimObject from C/C++ code.
/// @param object Object on which to execute the method call. /// @param object Object on which to execute the method call.
@ -802,8 +864,8 @@ namespace Con
/// char* result = execute(mysimobject, 3, argv); /// char* result = execute(mysimobject, 3, argv);
/// @endcode /// @endcode
/// NOTE: this function restores the console stack on return. /// NOTE: this function restores the console stack on return.
ConsoleValueRef execute(SimObject *object, S32 argc, const char* argv[], bool thisCallOnly = false); ConsoleValue execute(SimObject *object, S32 argc, const char* argv[], bool thisCallOnly = false);
ConsoleValueRef execute(SimObject *object, S32 argc, ConsoleValueRef argv[], bool thisCallOnly = false); ConsoleValue execute(SimObject *object, S32 argc, ConsoleValue argv[], bool thisCallOnly = false);
/// Executes a script file and compiles it for use in script. /// Executes a script file and compiles it for use in script.
/// ///
@ -821,13 +883,13 @@ namespace Con
/// @param echo Should we echo the string to the console? /// @param echo Should we echo the string to the console?
/// @param fileName Indicate what file this code is coming from; used in error reporting and such. /// @param fileName Indicate what file this code is coming from; used in error reporting and such.
/// NOTE: This function restores the console stack on return. /// NOTE: This function restores the console stack on return.
ConsoleValueRef evaluate(const char* string, bool echo = false, const char *fileName = NULL); ConsoleValue evaluate(const char* string, bool echo = false, const char *fileName = NULL);
/// Evaluate an arbitrary line of script. /// Evaluate an arbitrary line of script.
/// ///
/// This wraps dVsprintf(), so you can substitute parameters into the code being executed. /// This wraps dVsprintf(), so you can substitute parameters into the code being executed.
/// NOTE: This function restores the console stack on return. /// NOTE: This function restores the console stack on return.
ConsoleValueRef evaluatef(const char* string, ...); ConsoleValue evaluatef(const char* string, ...);
/// @} /// @}
@ -915,10 +977,10 @@ namespace Con
/// @see _EngineConsoleExecCallbackHelper /// @see _EngineConsoleExecCallbackHelper
/// ///
template<typename R, typename ...ArgTs> template<typename R, typename ...ArgTs>
ConsoleValueRef executef(R r, ArgTs ...argTs) ConsoleValue executef(R r, ArgTs ...argTs)
{ {
_EngineConsoleExecCallbackHelper<R> callback(r); _EngineConsoleExecCallbackHelper<R> callback(r);
return callback.template call<ConsoleValueRef>(argTs...); return std::move(callback.template call<ConsoleValue>(argTs...));
} }
/// } /// }
}; };

View file

@ -864,7 +864,7 @@ public:
(Vector<const char*>* vec) \ (Vector<const char*>* vec) \
{ \ { \
_CHECK_ENGINE_INITIALIZED( name, returnType ); \ _CHECK_ENGINE_INITIALIZED( name, returnType ); \
StringStackConsoleWrapper args(vec->size(), vec->address()); \ StringArrayToConsoleValueWrapper args(vec->size(), vec->address()); \
return EngineTypeTraits< returnType >::ReturnValue( \ return EngineTypeTraits< returnType >::ReturnValue( \
_fn ## name ## impl(NULL, args.count(), args) \ _fn ## name ## impl(NULL, args.count(), args) \
); \ ); \
@ -895,7 +895,7 @@ public:
(className* object, Vector<const char*>* vec) \ (className* object, Vector<const char*>* vec) \
{ \ { \
_CHECK_ENGINE_INITIALIZED( name, returnType ); \ _CHECK_ENGINE_INITIALIZED( name, returnType ); \
StringStackConsoleWrapper args(vec->size(), vec->address()); \ StringArrayToConsoleValueWrapper args(vec->size(), vec->address()); \
_ ## className ## name ## frame frame {}; \ _ ## className ## name ## frame frame {}; \
frame.object = static_cast< className* >( object ); \ frame.object = static_cast< className* >( object ); \
return EngineTypeTraits< returnType >::ReturnValue( \ return EngineTypeTraits< returnType >::ReturnValue( \
@ -1226,7 +1226,7 @@ public:
template<typename P1> struct _EngineConsoleExecCallbackHelper : public _BaseEngineConsoleCallbackHelper template<typename P1> struct _EngineConsoleExecCallbackHelper : public _BaseEngineConsoleCallbackHelper
{ {
private: private:
using Helper = engineAPI::detail::MarshallHelpers<ConsoleValueRef>; using Helper = engineAPI::detail::MarshallHelpers<ConsoleValue>;
public: public:
_EngineConsoleExecCallbackHelper( SimObject* pThis ) _EngineConsoleExecCallbackHelper( SimObject* pThis )

View file

@ -83,8 +83,6 @@ public:
virtual void process(SimObject *object)=0; virtual void process(SimObject *object)=0;
}; };
class ConsoleValueRef;
/// Implementation of schedule() function. /// Implementation of schedule() function.
/// ///
/// This allows you to set a console function to be /// This allows you to set a console function to be

View file

@ -83,7 +83,7 @@ DefineEngineStringlyVariadicMethod( GuiFilterCtrl, setValue, void, 3, 20, "(f1,
{ {
Filter filter; Filter filter;
StringStackWrapper args(argc - 2, argv + 2); ConsoleValueToStringArrayWrapper args(argc - 2, argv + 2);
filter.set(args.count(), args); filter.set(args.count(), args);
object->set(filter); object->set(filter);

View file

@ -102,8 +102,17 @@ typedef unsigned _int64 U64;
// disable warning caused by memory layer // disable warning caused by memory layer
// see msdn.microsoft.com "Compiler Warning (level 1) C4291" for more details // see msdn.microsoft.com "Compiler Warning (level 1) C4291" for more details
#pragma warning(disable: 4291) #pragma warning(disable: 4291)
#define TORQUE_FORCEINLINE __forceinline
#if __cplusplus >= 201703L
#define TORQUE_CASE_FALLTHROUGH [[fallthrough]];
#define TORQUE_UNLIKELY [[unlikely]]
#else
#define TORQUE_CASE_FALLTHROUGH __fallthrough
#define TORQUE_UNLIKELY
#endif
#endif // INCLUDED_TYPES_VISUALC_H #endif // INCLUDED_TYPES_VISUALC_H

View file

@ -2080,7 +2080,7 @@ static ConsoleDocFragment _ActionMapbind2(
DefineEngineStringlyVariadicMethod( ActionMap, bind, bool, 5, 10, "actionMap.bind( device, action, [modifier, spec, mod...], command )" DefineEngineStringlyVariadicMethod( ActionMap, bind, bool, 5, 10, "actionMap.bind( device, action, [modifier, spec, mod...], command )"
"@hide") "@hide")
{ {
StringStackWrapper args(argc - 2, argv + 2); ConsoleValueToStringArrayWrapper args(argc - 2, argv + 2);
return object->processBind( args.count(), args, NULL ); return object->processBind( args.count(), args, NULL );
} }
@ -2136,7 +2136,7 @@ DefineEngineStringlyVariadicMethod( ActionMap, bindObj, bool, 6, 11, "(device, a
return false; return false;
} }
StringStackWrapper args(argc - 3, argv + 2); ConsoleValueToStringArrayWrapper args(argc - 3, argv + 2);
return object->processBind( args.count(), args, simObject ); return object->processBind( args.count(), args, simObject );
} }