stringStack.cpp 11 KB

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