diff --git a/Engine/source/console/compiledEval.cpp b/Engine/source/console/compiledEval.cpp index 7b1275b30..8d9f5dfcd 100644 --- a/Engine/source/console/compiledEval.cpp +++ b/Engine/source/console/compiledEval.cpp @@ -87,7 +87,7 @@ struct IterStackRecord struct StringPos { /// The raw string data on the string stack. - const char* mString; + StringStackPtr mString; /// Current parsing position. U32 mIndex; @@ -288,6 +288,12 @@ inline void ExprEvalState::setStringVariable(const char *val) currentVariable->setStringValue(val); } +inline void ExprEvalState::setStringStackPtrVariable(StringStackPtr str) +{ + AssertFatal(currentVariable != NULL, "Invalid evaluator state - trying to set null variable!"); + currentVariable->setStringStackPtrValue(str); +} + inline void ExprEvalState::setCopyVariable() { if (copyVariable) @@ -493,15 +499,25 @@ ConsoleValueRef CodeBlock::exec(U32 ip, const char *functionName, Namespace *thi ConsoleValueRef ref = argv[i+1]; - if (argv[i+1].isString()) - gEvalState.setStringVariable(argv[i+1]); - else if (argv[i+1].isInt()) + switch(argv[i+1].getType()) + { + case ConsoleValue::TypeInternalInt: gEvalState.setIntVariable(argv[i+1]); - else if (argv[i+1].isFloat()) + break; + case ConsoleValue::TypeInternalFloat: gEvalState.setFloatVariable(argv[i+1]); - else + break; + case ConsoleValue::TypeInternalStringStackPtr: + gEvalState.setStringStackPtrVariable(argv[i+1].getStringStackPtrValue()); + break; + case ConsoleValue::TypeInternalStackString: + case ConsoleValue::TypeInternalString: + default: gEvalState.setStringVariable(argv[i+1]); + break; + } } + ip = ip + (fnArgc * 2) + (2 + 6 + 1); curFloatTable = functionFloats; curStringTable = functionStrings; @@ -583,7 +599,7 @@ ConsoleValueRef CodeBlock::exec(U32 ip, const char *functionName, Namespace *thi Con::gCurrentRoot = this->modPath; } const char * val; - const char *retValue; + StringStackPtr retValue; // note: anything returned is pushed to CSTK and will be invalidated on the next exec() ConsoleValueRef returnValue; @@ -1137,7 +1153,7 @@ breakContinue: // We're falling thru here on purpose. case OP_RETURN: - retValue = STR.getStringValue(); + retValue = STR.getStringValuePtr(); if( iterDepth > 0 ) { @@ -1149,13 +1165,13 @@ breakContinue: } STR.rewind(); - STR.setStringValue( retValue ); // Not nice but works. - retValue = STR.getStringValue(); + STR.setStringValue( StringStackPtrRef(retValue).getPtr(&STR) ); // Not nice but works. + retValue = STR.getStringValuePtr(); } // Previously the return value was on the stack and would be returned using STR.getStringValue(). // Now though we need to wrap it in a ConsoleValueRef - returnValue.value = CSTK.pushStackString(retValue); + returnValue.value = CSTK.pushStringStackPtr(retValue); goto execFinished; @@ -1992,7 +2008,7 @@ breakContinue: break; case OP_PUSH: STR.push(); - CSTK.pushString(STR.getPreviousStringValue()); + CSTK.pushStringStackPtr(STR.getPreviousStringValuePtr()); break; case OP_PUSH_UINT: CSTK.pushUINT(intStack[_UINT]); @@ -2073,7 +2089,7 @@ breakContinue: if( iter.mIsStringIter ) { - iter.mData.mStr.mString = STR.getStringValue(); + iter.mData.mStr.mString = STR.getStringValuePtr(); iter.mData.mStr.mIndex = 0; } else @@ -2111,7 +2127,7 @@ breakContinue: if( iter.mIsStringIter ) { - const char* str = iter.mData.mStr.mString; + const char* str = StringStackPtrRef(iter.mData.mStr.mString).getPtr(&STR); U32 startIndex = iter.mData.mStr.mIndex; U32 endIndex = startIndex; diff --git a/Engine/source/console/console.cpp b/Engine/source/console/console.cpp index 2000496d7..1260ed3e2 100644 --- a/Engine/source/console/console.cpp +++ b/Engine/source/console/console.cpp @@ -1756,6 +1756,8 @@ const char *ConsoleValue::getStringValue() { if(type == TypeInternalString || type == TypeInternalStackString) return sval; + else if (type == TypeInternalStringStackPtr) + return STR.mBuffer + (U32)sval; if(type == TypeInternalFloat) return Con::getData(TypeF32, &fval, 0); else if(type == TypeInternalInt) @@ -1764,10 +1766,18 @@ const char *ConsoleValue::getStringValue() return Con::getData(type, dataPtr, 0, enumTable); } +StringStackPtr ConsoleValue::getStringStackPtr() +{ + if (type == TypeInternalStringStackPtr) + return (U32)sval; + else + return (U32)-1; +} + bool ConsoleValue::getBoolValue() { - if(type == TypeInternalString || type == TypeInternalStackString) - return dAtob(sval); + if(type == TypeInternalString || type == TypeInternalStackString || type == TypeInternalStringStackPtr) + return dAtob(getStringValue()); if(type == TypeInternalFloat) return fval > 0; else if(type == TypeInternalInt) @@ -1791,7 +1801,7 @@ void ConsoleValue::setIntValue(U32 val) ival = val; if(sval != typeValueEmpty) { - if (type != TypeInternalStackString) dFree(sval); + if (type != TypeInternalStackString && type != TypeInternalStringStackPtr) dFree(sval); sval = typeValueEmpty; } type = TypeInternalInt; @@ -1816,7 +1826,7 @@ void ConsoleValue::setFloatValue(F32 val) ival = static_cast(val); if(sval != typeValueEmpty) { - if (type != TypeInternalStackString) dFree(sval); + if (type != TypeInternalStackString && type != TypeInternalStringStackPtr) dFree(sval); sval = typeValueEmpty; } type = TypeInternalFloat; diff --git a/Engine/source/console/console.h b/Engine/source/console/console.h index 52e82eee4..4ca0c8da8 100644 --- a/Engine/source/console/console.h +++ b/Engine/source/console/console.h @@ -44,6 +44,8 @@ struct ConsoleFunctionHeader; class EngineEnumTable; typedef EngineEnumTable EnumTable; +typedef U32 StringStackPtr; + template< typename T > S32 TYPEID(); @@ -121,8 +123,9 @@ public: enum { - TypeInternalInt = -4, - TypeInternalFloat = -3, + TypeInternalInt = -5, + TypeInternalFloat = -4, + TypeInternalStringStackPtr = -3, TypeInternalStackString = -2, TypeInternalString = -1, }; @@ -166,6 +169,7 @@ public: S32 getSignedIntValue(); F32 getFloatValue(); const char *getStringValue(); + StringStackPtr getStringStackPtr(); bool getBoolValue(); void setIntValue(U32 val); @@ -173,6 +177,7 @@ public: void setFloatValue(F32 val); void setStringValue(const char *value); void setStackStringValue(const char *value); + void setStringStackPtrValue(StringStackPtr ptr); void setBoolValue(bool val); void init() @@ -187,7 +192,7 @@ public: void cleanup() { if (type <= TypeInternalString && - sval != typeValueEmpty && type != TypeInternalStackString ) + sval != typeValueEmpty && type != TypeInternalStackString && type != TypeInternalStringStackPtr) dFree(sval); sval = typeValueEmpty; type = ConsoleValue::TypeInternalString; @@ -219,6 +224,7 @@ public: static ConsoleValueRef fromValue(ConsoleValue *value) { ConsoleValueRef ref; ref.value = value; return ref; } const char *getStringValue() { return value ? value->getStringValue() : ""; } + StringStackPtr getStringStackPtrValue() { return value ? value->getStringStackPtr() : 0; } inline U32 getIntValue() { return value ? value->getIntValue() : 0; } inline S32 getSignedIntValue() { return value ? value->getSignedIntValue() : 0; } @@ -231,10 +237,12 @@ public: inline operator S32() { return getSignedIntValue(); } inline operator F32() { return getFloatValue(); } inline operator bool() { return getBoolValue(); } - - inline bool isString() { return value ? value->type >= ConsoleValue::TypeInternalStackString : true; } + + inline bool isStringStackPtr() { return value ? value->type == ConsoleValue::TypeInternalStringStackPtr : false; } + inline bool isString() { return value ? value->type >= ConsoleValue::TypeInternalStringStackPtr : true; } inline bool isInt() { return value ? value->type == ConsoleValue::TypeInternalInt : false; } inline bool isFloat() { return value ? value->type == ConsoleValue::TypeInternalFloat : false; } + inline S32 getType() { return value ? value->type : -1; } // Note: operators replace value ConsoleValueRef& operator=(const ConsoleValueRef &other); diff --git a/Engine/source/console/consoleInternal.cpp b/Engine/source/console/consoleInternal.cpp index 1c41f4012..e72ddee80 100644 --- a/Engine/source/console/consoleInternal.cpp +++ b/Engine/source/console/consoleInternal.cpp @@ -512,7 +512,7 @@ void ConsoleValue::setStringValue(const char * value) */ if (value == typeValueEmpty) { - if (sval && sval != typeValueEmpty && type != TypeInternalStackString) dFree(sval); + if (sval && sval != typeValueEmpty && type != TypeInternalStackString && type != TypeInternalStringStackPtr) dFree(sval); sval = typeValueEmpty; bufferLen = 0; fval = 0.f; @@ -541,7 +541,7 @@ void ConsoleValue::setStringValue(const char * value) // may as well pad to the next cache line U32 newLen = ((stringLen + 1) + 15) & ~15; - if(sval == typeValueEmpty || type == TypeInternalStackString) + if(sval == typeValueEmpty || type == TypeInternalStackString || type == TypeInternalStringStackPtr) sval = (char *) dMalloc(newLen); else if(newLen > bufferLen) sval = (char *) dRealloc(sval, newLen); @@ -556,7 +556,7 @@ void ConsoleValue::setStringValue(const char * value) } -void ConsoleValue::setStackStringValue(const char * value) +void ConsoleValue::setStackStringValue(const char *value) { if (value == NULL) value = typeValueEmpty; @@ -564,7 +564,7 @@ void ConsoleValue::setStackStringValue(const char * value) { if (value == typeValueEmpty) { - if (sval && sval != typeValueEmpty && type != ConsoleValue::TypeInternalStackString) dFree(sval); + if (sval && sval != typeValueEmpty && type != ConsoleValue::TypeInternalStackString && type != ConsoleValue::TypeInternalStringStackPtr) dFree(sval); sval = typeValueEmpty; bufferLen = 0; fval = 0.f; @@ -586,13 +586,42 @@ void ConsoleValue::setStackStringValue(const char * value) } type = TypeInternalStackString; - sval = (char*)value; + sval = (char*)value; bufferLen = stringLen; } else Con::setData(type, dataPtr, 0, 1, &value, enumTable); } +void ConsoleValue::setStringStackPtrValue(StringStackPtr ptrValue) +{ + if(type <= ConsoleValue::TypeInternalString) + { + const char *value = StringStackPtrRef(ptrValue).getPtr(&STR); + if (sval && sval != typeValueEmpty && type != ConsoleValue::TypeInternalStackString && type != TypeInternalStringStackPtr) dFree(sval); + + U32 stringLen = dStrlen(value); + if(stringLen < 256) + { + fval = dAtof(value); + ival = dAtoi(value); + } + else + { + fval = 0.f; + ival = 0; + } + + type = TypeInternalStringStackPtr; + sval = (char*)(value - STR.mBuffer); + bufferLen = stringLen; + } + else + { + const char *value = StringStackPtrRef(ptrValue).getPtr(&STR); + Con::setData(type, dataPtr, 0, 1, &value, enumTable); + } +} S32 Dictionary::getIntVariable(StringTableEntry name, bool *entValid) { @@ -651,7 +680,8 @@ Dictionary::Entry* Dictionary::addVariable( const char *name, Entry *ent = add(StringTable->insert(name)); if ( ent->value.type <= ConsoleValue::TypeInternalString && - ent->value.sval != typeValueEmpty && ent->value.type != ConsoleValue::TypeInternalStackString ) + ent->value.sval != typeValueEmpty && + ent->value.type != ConsoleValue::TypeInternalStackString && ent->value.type != ConsoleValue::TypeInternalStringStackPtr ) dFree(ent->value.sval); ent->value.type = type; diff --git a/Engine/source/console/consoleInternal.h b/Engine/source/console/consoleInternal.h index 761874c2f..35ebff800 100644 --- a/Engine/source/console/consoleInternal.h +++ b/Engine/source/console/consoleInternal.h @@ -367,6 +367,22 @@ public: notify->trigger(); } + void setStringStackPtrValue(StringStackPtr newValue) + { + if( mIsConstant ) + { + Con::errorf( "Cannot assign value to constant '%s'.", name ); + return; + } + + value.setStringStackPtrValue(newValue); + + + // Fire off the notification if we have one. + if ( notify ) + notify->trigger(); + } + void setStringValue(const char *newValue) { if( mIsConstant ) @@ -495,6 +511,7 @@ public: void setIntVariable(S32 val); void setFloatVariable(F64 val); void setStringVariable(const char *str); + void setStringStackPtrVariable(StringStackPtr str); void setCopyVariable(); void pushFrame(StringTableEntry frameName, Namespace *ns); diff --git a/Engine/source/console/stringStack.cpp b/Engine/source/console/stringStack.cpp index 72c1efa98..45fd83740 100644 --- a/Engine/source/console/stringStack.cpp +++ b/Engine/source/console/stringStack.cpp @@ -90,6 +90,8 @@ void ConsoleValueStack::pushValue(ConsoleValue &variable) mStack[mStackPos++].setIntValue((S32)variable.getIntValue()); case ConsoleValue::TypeInternalFloat: mStack[mStackPos++].setFloatValue((F32)variable.getFloatValue()); + case ConsoleValue::TypeInternalStringStackPtr: + mStack[mStackPos++].setStringStackPtrValue(variable.getStringStackPtr()); default: mStack[mStackPos++].setStringValue(variable.getStringValue()); } @@ -151,6 +153,19 @@ ConsoleValue *ConsoleValueStack::pushStackString(const char *value) return &mStack[mStackPos-1]; } +ConsoleValue *ConsoleValueStack::pushStringStackPtr(StringStackPtr value) +{ + if (mStackPos == ConsoleValueStack::MaxStackDepth) { + AssertFatal(false, "Console Value Stack is empty"); + return NULL; + } + + //Con::printf("[%i]CSTK pushStringStackPtr %s", mStackPos, StringStackPtrRef(value).getPtr(&STR)); + + mStack[mStackPos++].setStringStackPtrValue(value); + return &mStack[mStackPos-1]; +} + ConsoleValue *ConsoleValueStack::pushUINT(U32 value) { if (mStackPos == ConsoleValueStack::MaxStackDepth) { diff --git a/Engine/source/console/stringStack.h b/Engine/source/console/stringStack.h index 4b869bb4b..d76ad71ec 100644 --- a/Engine/source/console/stringStack.h +++ b/Engine/source/console/stringStack.h @@ -35,8 +35,21 @@ #include "console/console.h" #endif +typedef U32 StringStackPtr; +struct StringStack; +/// Helper class which stores a relative pointer in the StringStack buffer +class StringStackPtrRef +{ +public: + StringStackPtrRef() : mOffset(0) {;} + StringStackPtrRef(StringStackPtr offset) : mOffset(offset) {;} + StringStackPtr mOffset; + + /// Get pointer to string in stack stk + inline char *getPtr(StringStack *stk); +}; /// Core stack for interpreter operations. /// @@ -199,6 +212,16 @@ struct StringStack return mBuffer + mStartOffsets[mStartStackSize-1]; } + inline StringStackPtr getStringValuePtr() + { + return (getStringValue() - mBuffer); + } + + inline StringStackPtr getPreviousStringValuePtr() + { + return (getPreviousStringValue() - mBuffer); + } + /// Advance the start stack, placing a zero length string on the top. /// /// @note You should use StringStack::push, not this, if you want to @@ -322,6 +345,7 @@ public: ConsoleValue *pushString(const char *value); ConsoleValue *pushStackString(const char *value); + ConsoleValue *pushStringStackPtr(StringStackPtr ptr); ConsoleValue *pushUINT(U32 value); ConsoleValue *pushFLT(float value); @@ -345,4 +369,6 @@ public: extern StringStack STR; extern ConsoleValueStack CSTK; +inline char* StringStackPtrRef::getPtr(StringStack *stk) { return stk->mBuffer + mOffset; } + #endif