stringStack.cpp
Engine/source/console/stringStack.cpp
Public Variables
Detailed Description
Public Variables
ConsoleValue gNothing
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include <stdio.h> 25#include "console/consoleInternal.h" 26#include "console/stringStack.h" 27 28StringStack::StringStack() 29{ 30 mBufferSize = 0; 31 mBuffer = NULL; 32 mArgBufferSize = 0; 33 mArgBuffer = NULL; 34 for (U32 i = 0; i < MaxArgs; i++) 35 mArgV[i] = ""; 36 dMemset(mFrameOffsets, 0, sizeof(mFrameOffsets)); 37 dMemset(mStartOffsets, 0, sizeof(mStartOffsets)); 38 mNumFrames = 0; 39 mArgc = 0; 40 mStart = 0; 41 mLen = 0; 42 mStartStackSize = 0; 43 mFunctionOffset = 0; 44 validateBufferSize(8192); 45 validateArgBufferSize(2048); 46 dMemset(mBuffer, '\0', mBufferSize); 47 dMemset(mArgBuffer, '\0', mArgBufferSize); 48} 49 50StringStack::~StringStack() 51{ 52 if( mBuffer ) 53 dFree( mBuffer ); 54 if( mArgBuffer ) 55 dFree( mArgBuffer ); 56} 57 58void StringStack::validateBufferSize(U32 size) 59{ 60 if(size > mBufferSize) 61 { 62 mBufferSize = size + 2048; 63 mBuffer = (char *) dRealloc(mBuffer, mBufferSize); 64 } 65} 66 67void StringStack::validateArgBufferSize(U32 size) 68{ 69 if(size > mArgBufferSize) 70 { 71 mArgBufferSize = size + 2048; 72 mArgBuffer = (char *) dRealloc(mArgBuffer, mArgBufferSize); 73 } 74} 75 76void StringStack::setIntValue(U32 i) 77{ 78 validateBufferSize(mStart + 32); 79 dSprintf(mBuffer + mStart, 32, "%d", i); 80 mLen = dStrlen(mBuffer + mStart); 81} 82 83void StringStack::setFloatValue(F64 v) 84{ 85 validateBufferSize(mStart + 32); 86 dSprintf(mBuffer + mStart, 32, "%g", v); 87 mLen = dStrlen(mBuffer + mStart); 88} 89 90char *StringStack::getReturnBuffer(U32 size) 91{ 92 if(size > ReturnBufferSpace) 93 { 94 AssertFatal(Con::isMainThread(), "Manipulating return buffer from a secondary thread!"); 95 validateArgBufferSize(size); 96 return mArgBuffer; 97 } 98 else 99 { 100 validateBufferSize(mStart + size); 101 return mBuffer + mStart; 102 } 103} 104 105char *StringStack::getArgBuffer(U32 size) 106{ 107 AssertFatal(Con::isMainThread(), "Manipulating console arg buffer from a secondary thread!"); 108 validateBufferSize(mStart + mFunctionOffset + size); 109 char *ret = mBuffer + mStart + mFunctionOffset; 110 mFunctionOffset += size; 111 return ret; 112} 113 114void StringStack::clearFunctionOffset() 115{ 116 //Con::printf("StringStack mFunctionOffset = 0 (from %i)", mFunctionOffset); 117 mFunctionOffset = 0; 118} 119 120void StringStack::setStringValue(const char *s) 121{ 122 if(!s) 123 { 124 mLen = 0; 125 mBuffer[mStart] = 0; 126 return; 127 } 128 mLen = dStrlen(s); 129 130 validateBufferSize(mStart + mLen + 2); 131 dStrcpy(mBuffer + mStart, s, mBufferSize - mStart); 132} 133 134void StringStack::advance() 135{ 136 mStartOffsets[mStartStackSize++] = mStart; 137 mStart += mLen; 138 mLen = 0; 139} 140 141void StringStack::advanceChar(char c) 142{ 143 mStartOffsets[mStartStackSize++] = mStart; 144 mStart += mLen; 145 mBuffer[mStart] = c; 146 mBuffer[mStart+1] = 0; 147 mStart += 1; 148 mLen = 0; 149} 150 151void StringStack::push() 152{ 153 advanceChar(0); 154} 155 156void StringStack::rewind() 157{ 158 mStart = mStartOffsets[--mStartStackSize]; 159 mLen = dStrlen(mBuffer + mStart); 160} 161 162void StringStack::rewindTerminate() 163{ 164 mBuffer[mStart] = 0; 165 mStart = mStartOffsets[--mStartStackSize]; 166 mLen = dStrlen(mBuffer + mStart); 167} 168 169U32 StringStack::compare() 170{ 171 // Figure out the 1st and 2nd item offsets. 172 U32 oldStart = mStart; 173 mStart = mStartOffsets[--mStartStackSize]; 174 175 // Compare current and previous strings. 176 U32 ret = !dStricmp(mBuffer + mStart, mBuffer + oldStart); 177 178 // Put an empty string on the top of the stack. 179 mLen = 0; 180 mBuffer[mStart] = 0; 181 182 return ret; 183} 184 185void StringStack::pushFrame() 186{ 187 //Con::printf("StringStack pushFrame [frame=%i, start=%i]", mNumFrames, mStartStackSize); 188 mFrameOffsets[mNumFrames++] = mStartStackSize; 189 mStartOffsets[mStartStackSize++] = mStart; 190 mStart += ReturnBufferSpace; 191 validateBufferSize(0); 192} 193 194void StringStack::popFrame() 195{ 196 //Con::printf("StringStack popFrame [frame=%i, start=%i]", mNumFrames, mStartStackSize); 197 mStartStackSize = mFrameOffsets[--mNumFrames]; 198 mStart = mStartOffsets[mStartStackSize]; 199 mLen = 0; 200} 201 202void StringStack::clearFrames() 203{ 204 //Con::printf("StringStack clearFrames"); 205 mNumFrames = 0; 206 mStart = 0; 207 mLen = 0; 208 mStartStackSize = 0; 209 mFunctionOffset = 0; 210} 211 212 213void ConsoleValueStack::getArgcArgv(StringTableEntry name, U32 *argc, ConsoleValueRef **in_argv, bool popStackFrame /* = false */) 214{ 215 U32 startStack = mStackFrames[mFrame-1]; 216 U32 argCount = getMin(mStackPos - startStack, (U32)MaxArgs - 1); 217 218 *in_argv = mArgv; 219 mArgv[0].value = CSTK.pushStackString(name); 220 221 for(U32 i = 0; i < argCount; i++) { 222 ConsoleValueRef *ref = &mArgv[i+1]; 223 ref->value = &mStack[startStack + i]; 224 } 225 argCount++; 226 227 *argc = argCount; 228 229 if(popStackFrame) 230 popFrame(); 231} 232 233ConsoleValueStack::ConsoleValueStack() : 234mFrame(0), 235mStackPos(0) 236{ 237 for (int i=0; i<ConsoleValueStack::MaxStackDepth; i++) { 238 mStack[i].init(); 239 mStack[i].type = ConsoleValue::TypeInternalString; 240 } 241 dMemset(mStackFrames, 0, sizeof(mStackFrames)); 242} 243 244ConsoleValueStack::~ConsoleValueStack() 245{ 246} 247 248void ConsoleValueStack::pushVar(ConsoleValue *variable) 249{ 250 if (mStackPos == ConsoleValueStack::MaxStackDepth) { 251 AssertFatal(false, "Console Value Stack is empty"); 252 return; 253 } 254 255 switch (variable->type) 256 { 257 case ConsoleValue::TypeInternalInt: 258 mStack[mStackPos++].setIntValue((S32)variable->getIntValue()); 259 case ConsoleValue::TypeInternalFloat: 260 mStack[mStackPos++].setFloatValue((F32)variable->getFloatValue()); 261 default: 262 mStack[mStackPos++].setStackStringValue(variable->getStringValue()); 263 } 264} 265 266void ConsoleValueStack::pushValue(ConsoleValue &variable) 267{ 268 if (mStackPos == ConsoleValueStack::MaxStackDepth) { 269 AssertFatal(false, "Console Value Stack is empty"); 270 return; 271 } 272 273 switch (variable.type) 274 { 275 case ConsoleValue::TypeInternalInt: 276 mStack[mStackPos++].setIntValue((S32)variable.getIntValue()); 277 case ConsoleValue::TypeInternalFloat: 278 mStack[mStackPos++].setFloatValue((F32)variable.getFloatValue()); 279 case ConsoleValue::TypeInternalStringStackPtr: 280 mStack[mStackPos++].setStringStackPtrValue(variable.getStringStackPtr()); 281 default: 282 mStack[mStackPos++].setStringValue(variable.getStringValue()); 283 } 284} 285 286ConsoleValue* ConsoleValueStack::reserveValues(U32 count) 287{ 288 U32 startPos = mStackPos; 289 if (startPos+count >= ConsoleValueStack::MaxStackDepth) { 290 AssertFatal(false, "Console Value Stack is empty"); 291 return NULL; 292 } 293 294 //Con::printf("[%i]CSTK reserveValues %i", mStackPos, count); 295 mStackPos += count; 296 return &mStack[startPos]; 297} 298 299bool ConsoleValueStack::reserveValues(U32 count, ConsoleValueRef *outValues) 300{ 301 U32 startPos = mStackPos; 302 if (startPos+count >= ConsoleValueStack::MaxStackDepth) { 303 AssertFatal(false, "Console Value Stack is empty"); 304 return false; 305 } 306 307 //Con::printf("[%i]CSTK reserveValues %i", mStackPos, count); 308 for (U32 i=0; i<count; i++) 309 { 310 outValues[i].value = &mStack[mStackPos+i]; 311 } 312 mStackPos += count; 313 return true; 314} 315 316ConsoleValue *ConsoleValueStack::pushString(const char *value) 317{ 318 if (mStackPos == ConsoleValueStack::MaxStackDepth) { 319 AssertFatal(false, "Console Value Stack is empty"); 320 return NULL; 321 } 322 323 //Con::printf("[%i]CSTK pushString %s", mStackPos, value); 324 325 mStack[mStackPos++].setStringValue(value); 326 return &mStack[mStackPos-1]; 327} 328 329ConsoleValue *ConsoleValueStack::pushStackString(const char *value) 330{ 331 if (mStackPos == ConsoleValueStack::MaxStackDepth) { 332 AssertFatal(false, "Console Value Stack is empty"); 333 return NULL; 334 } 335 336 //Con::printf("[%i]CSTK pushString %s", mStackPos, value); 337 338 mStack[mStackPos++].setStackStringValue(value); 339 return &mStack[mStackPos-1]; 340} 341 342ConsoleValue *ConsoleValueStack::pushStringStackPtr(StringStackPtr value) 343{ 344 if (mStackPos == ConsoleValueStack::MaxStackDepth) { 345 AssertFatal(false, "Console Value Stack is empty"); 346 return NULL; 347 } 348 349 //Con::printf("[%i]CSTK pushStringStackPtr %s", mStackPos, StringStackPtrRef(value).getPtr(&STR)); 350 351 mStack[mStackPos++].setStringStackPtrValue(value); 352 return &mStack[mStackPos-1]; 353} 354 355ConsoleValue *ConsoleValueStack::pushUINT(U32 value) 356{ 357 if (mStackPos == ConsoleValueStack::MaxStackDepth) { 358 AssertFatal(false, "Console Value Stack is empty"); 359 return NULL; 360 } 361 362 //Con::printf("[%i]CSTK pushUINT %i", mStackPos, value); 363 364 mStack[mStackPos++].setIntValue(value); 365 return &mStack[mStackPos-1]; 366} 367 368ConsoleValue *ConsoleValueStack::pushFLT(float value) 369{ 370 if (mStackPos == ConsoleValueStack::MaxStackDepth) { 371 AssertFatal(false, "Console Value Stack is empty"); 372 return NULL; 373 } 374 375 //Con::printf("[%i]CSTK pushFLT %f", mStackPos, value); 376 377 mStack[mStackPos++].setFloatValue(value); 378 return &mStack[mStackPos-1]; 379} 380 381static ConsoleValue gNothing; 382 383ConsoleValue* ConsoleValueStack::pop() 384{ 385 if (mStackPos == 0) { 386 AssertFatal(false, "Console Value Stack is empty"); 387 return &gNothing; 388 } 389 390 return &mStack[--mStackPos]; 391} 392 393void ConsoleValueStack::pushFrame() 394{ 395 //Con::printf("CSTK pushFrame[%i] (%i)", mFrame, mStackPos); 396 mStackFrames[mFrame++] = mStackPos; 397} 398 399void ConsoleValueStack::resetFrame() 400{ 401 if (mFrame == 0) { 402 mStackPos = 0; 403 return; 404 } 405 406 U32 start = mStackFrames[mFrame-1]; 407 //for (U32 i=start; i<mStackPos; i++) { 408 //mStack[i].clear(); 409 //} 410 mStackPos = start; 411 //Con::printf("CSTK resetFrame to %i", mStackPos); 412} 413 414void ConsoleValueStack::clearFrames() 415{ 416 mStackPos = 0; 417 mFrame = 0; 418} 419 420void ConsoleValueStack::popFrame() 421{ 422 //Con::printf("CSTK popFrame"); 423 if (mFrame == 0) { 424 // Go back to start 425 mStackPos = 0; 426 return; 427 } 428 429 U32 start = mStackFrames[mFrame-1]; 430 //for (U32 i=start; i<mStackPos; i++) { 431 //mStack[i].clear(); 432 //} 433 mStackPos = start; 434 mFrame--; 435} 436