stringStack.h

Engine/source/console/stringStack.h

More...

Classes:

class

Core stack for interpreter operations.

class

Helper class which stores a relative pointer in the StringStack buffer.

Public Typedefs

StringStackPtr 

Detailed Description

Public Typedefs

typedef U32 StringStackPtr 

Public Variables

ConsoleValueStack CSTK 
StringStack STR 
  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#ifndef _STRINGSTACK_H_
 25#define _STRINGSTACK_H_
 26
 27#ifndef _STRINGFUNCTIONS_H_
 28#include "core/strings/stringFunctions.h"
 29#endif
 30
 31#ifndef _STRINGTABLE_H_
 32#include "core/stringTable.h"
 33#endif
 34
 35#ifndef _CONSOLE_H_
 36#include "console/console.h"
 37#endif
 38
 39typedef U32 StringStackPtr;
 40struct StringStack;
 41
 42/// Helper class which stores a relative pointer in the StringStack buffer
 43class StringStackPtrRef
 44{
 45public:
 46   StringStackPtrRef() : mOffset(0) {;}
 47   StringStackPtrRef(StringStackPtr offset) : mOffset(offset) {;}
 48
 49   StringStackPtr mOffset;
 50
 51   /// Get pointer to string in stack stk
 52   inline char *getPtr(StringStack *stk);
 53};
 54
 55/// Core stack for interpreter operations.
 56///
 57/// This class provides some powerful semantics for working with strings, and is
 58/// used heavily by the console interpreter.
 59struct StringStack
 60{
 61   enum {
 62      MaxStackDepth = 1024,
 63      MaxArgs = 20,
 64      ReturnBufferSpace = 512
 65   };
 66   char *mBuffer;
 67   U32   mBufferSize;
 68   const char *mArgV[MaxArgs];
 69   U32 mFrameOffsets[MaxStackDepth];
 70   U32 mStartOffsets[MaxStackDepth];
 71
 72   U32 mNumFrames;
 73   U32 mArgc;
 74
 75   U32 mStart;
 76   U32 mLen;
 77   U32 mStartStackSize;
 78   U32 mFunctionOffset;
 79
 80   U32 mArgBufferSize;
 81   char *mArgBuffer;
 82
 83   void validateBufferSize(U32 size)
 84   {
 85      if(size > mBufferSize)
 86      {
 87         mBufferSize = size + 2048;
 88         mBuffer = (char *) dRealloc(mBuffer, mBufferSize);
 89      }
 90   }
 91
 92   void validateArgBufferSize(U32 size)
 93   {
 94      if(size > mArgBufferSize)
 95      {
 96         mArgBufferSize = size + 2048;
 97         mArgBuffer = (char *) dRealloc(mArgBuffer, mArgBufferSize);
 98      }
 99   }
100
101   StringStack()
102   {
103      mBufferSize = 0;
104      mBuffer = NULL;
105      mArgBufferSize = 0;
106      mArgBuffer = NULL;
107      mNumFrames = 0;
108      mStart = 0;
109      mLen = 0;
110      mStartStackSize = 0;
111      mFunctionOffset = 0;
112      validateBufferSize(8192);
113      validateArgBufferSize(2048);
114      dMemset(mBuffer, '\0', mBufferSize);
115      dMemset(mArgBuffer, '\0', mArgBufferSize);
116   }
117   ~StringStack()
118   {
119      if( mBuffer )
120         dFree( mBuffer );
121      if( mArgBuffer )
122         dFree( mArgBuffer );
123   }
124
125   /// Set the top of the stack to be an integer value.
126   void setIntValue(U32 i)
127   {
128      validateBufferSize(mStart + 32);
129      dSprintf(mBuffer + mStart, 32, "%d", i);
130      mLen = dStrlen(mBuffer + mStart);
131   }
132
133   /// Set the top of the stack to be a float value.
134   void setFloatValue(F64 v)
135   {
136      validateBufferSize(mStart + 32);
137      dSprintf(mBuffer + mStart, 32, "%g", v);
138      mLen = dStrlen(mBuffer + mStart);
139   }
140
141   /// Return a temporary buffer we can use to return data.
142   char* getReturnBuffer(U32 size)
143   {
144      AssertFatal(Con::isMainThread(), "Manipulating return buffer from a secondary thread!");
145      validateArgBufferSize(size);
146      return mArgBuffer;
147   }
148
149   /// Return a buffer we can use for arguments.
150   ///
151   /// This updates the function offset.
152   char *getArgBuffer(U32 size)
153   {
154      AssertFatal(Con::isMainThread(), "Manipulating console arg buffer from a secondary thread!");
155      validateBufferSize(mStart + mFunctionOffset + size);
156      char *ret = mBuffer + mStart + mFunctionOffset;
157      mFunctionOffset += size;
158      return ret;
159   }
160
161   /// Clear the function offset.
162   void clearFunctionOffset()
163   {
164      //Con::printf("StringStack mFunctionOffset = 0 (from %i)", mFunctionOffset);
165      mFunctionOffset = 0;
166   }
167
168   /// Set a string value on the top of the stack.
169   void setStringValue(const char *s)
170   {
171      if(!s)
172      {
173         mLen = 0;
174         mBuffer[mStart] = 0;
175         return;
176      }
177      mLen = dStrlen(s);
178
179      validateBufferSize(mStart + mLen + 2);
180      dStrcpy(mBuffer + mStart, s);
181   }
182
183   /// Get the top of the stack, as a StringTableEntry.
184   ///
185   /// @note Don't free this memory!
186   inline StringTableEntry getSTValue()
187   {
188      return StringTable->insert(mBuffer + mStart);
189   }
190
191   /// Get an integer representation of the top of the stack.
192   inline U32 getIntValue()
193   {
194      return dAtoi(mBuffer + mStart);
195   }
196
197   /// Get a float representation of the top of the stack.
198   inline F64 getFloatValue()
199   {
200      return dAtof(mBuffer + mStart);
201   }
202
203   /// Get a string representation of the top of the stack.
204   ///
205   /// @note This returns a pointer to the actual top of the stack, be careful!
206   inline const char *getStringValue()
207   {
208      return mBuffer + mStart;
209   }
210
211   inline const char *getPreviousStringValue()
212   {
213      return mBuffer + mStartOffsets[mStartStackSize-1];
214   }
215
216   inline StringStackPtr getStringValuePtr()
217   {
218      return (getStringValue() - mBuffer);
219   }
220
221   inline StringStackPtr getPreviousStringValuePtr()
222   {
223      return (getPreviousStringValue() - mBuffer);
224   }
225
226   /// Advance the start stack, placing a zero length string on the top.
227   ///
228   /// @note You should use StringStack::push, not this, if you want to
229   ///       properly push the stack.
230   void advance()
231   {
232      mStartOffsets[mStartStackSize++] = mStart;
233      mStart += mLen;
234      mLen = 0;
235   }
236
237   /// Advance the start stack, placing a single character, null-terminated strong
238   /// on the top.
239   ///
240   /// @note You should use StringStack::push, not this, if you want to
241   ///       properly push the stack.
242   void advanceChar(char c)
243   {
244      mStartOffsets[mStartStackSize++] = mStart;
245      mStart += mLen;
246      mBuffer[mStart] = c;
247      mBuffer[mStart+1] = 0;
248      mStart += 1;
249      mLen = 0;
250   }
251
252   /// Push the stack, placing a zero-length string on the top.
253   void push()
254   {
255      advanceChar(0);
256   }
257
258   inline void setLen(U32 newlen)
259   {
260      mLen = newlen;
261   }
262
263   /// Pop the start stack.
264   void rewind()
265   {
266      mStart = mStartOffsets[--mStartStackSize];
267      mLen = dStrlen(mBuffer + mStart);
268   }
269
270   // Terminate the current string, and pop the start stack.
271   void rewindTerminate()
272   {
273      mBuffer[mStart] = 0;
274      mStart = mStartOffsets[--mStartStackSize];
275      mLen   = dStrlen(mBuffer + mStart);
276   }
277
278   /// Compare 1st and 2nd items on stack, consuming them in the process,
279   /// and returning true if they matched, false if they didn't.
280   U32 compare()
281   {
282      // Figure out the 1st and 2nd item offsets.
283      U32 oldStart = mStart;
284      mStart = mStartOffsets[--mStartStackSize];
285
286      // Compare current and previous strings.
287      U32 ret = !dStricmp(mBuffer + mStart, mBuffer + oldStart);
288
289      // Put an empty string on the top of the stack.
290      mLen = 0;
291      mBuffer[mStart] = 0;
292
293      return ret;
294   }
295
296   void pushFrame()
297   {
298      //Con::printf("StringStack pushFrame [frame=%i, start=%i]", mNumFrames, mStartStackSize);
299      mFrameOffsets[mNumFrames++] = mStartStackSize;
300      mStartOffsets[mStartStackSize++] = mStart;
301      mStart += ReturnBufferSpace;
302      validateBufferSize(0);
303   }
304
305   void popFrame()
306   {
307      //Con::printf("StringStack popFrame [frame=%i, start=%i]", mNumFrames, mStartStackSize);
308      mStartStackSize = mFrameOffsets[--mNumFrames];
309      mStart = mStartOffsets[mStartStackSize];
310      mLen = 0;
311   }
312
313   void clearFrames()
314   {
315      //Con::printf("StringStack clearFrames");
316      mNumFrames = 0;
317      mStart = 0;
318      mLen = 0;
319      mStartStackSize = 0;
320      mFunctionOffset = 0;
321   }
322
323   /// Get the arguments for a function call from the stack.
324   void getArgcArgv(StringTableEntry name, U32 *argc, const char ***in_argv, bool popStackFrame = false);
325};
326
327
328// New console value stack
329class ConsoleValueStack
330{
331   enum {
332      MaxStackDepth = 1024,
333      MaxArgs = 20,
334      ReturnBufferSpace = 512
335   };
336
337public:
338   ConsoleValueStack();
339   ~ConsoleValueStack();
340
341   void pushVar(ConsoleValue *variable);
342   void pushValue(ConsoleValue &value);
343   ConsoleValue* reserveValues(U32 numValues);
344   bool reserveValues(U32 numValues, ConsoleValueRef *values);
345   ConsoleValue* pop();
346
347   ConsoleValue *pushString(const char *value);
348   ConsoleValue *pushStackString(const char *value);
349   ConsoleValue *pushStringStackPtr(StringStackPtr ptr);
350   ConsoleValue *pushUINT(U32 value);
351   ConsoleValue *pushFLT(float value);
352
353   void pushFrame();
354   void popFrame();
355
356   void resetFrame();
357   void clearFrames();
358
359   void getArgcArgv(StringTableEntry name, U32 *argc, ConsoleValueRef **in_argv, bool popStackFrame = false);
360
361   ConsoleValue mStack[MaxStackDepth];
362   U32 mStackFrames[MaxStackDepth];
363
364   U32 mFrame;
365   U32 mStackPos;
366
367   ConsoleValueRef mArgv[MaxArgs];
368};
369
370extern StringStack STR;
371extern ConsoleValueStack CSTK;
372
373inline char* StringStackPtrRef::getPtr(StringStack *stk) { return stk->mBuffer + mOffset; }
374
375#endif
376